mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-28 12:11:56 +01:00
Renaming project because of cocoapods name clash with HardcoreData :(
This commit is contained in:
68
CoreStore/Internal/AssociatedObjects.swift
Normal file
68
CoreStore/Internal/AssociatedObjects.swift
Normal file
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// NSObject+CoreStore.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright (c) 2014 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
internal func getAssociatedObjectForKey<T: AnyObject>(key: UnsafePointer<Void>, inObject object: AnyObject) -> T? {
|
||||
|
||||
switch objc_getAssociatedObject(object, key) {
|
||||
|
||||
case let associatedObject as T:
|
||||
return associatedObject
|
||||
|
||||
case let associatedObject as WeakObject:
|
||||
return associatedObject.object as? T
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
internal func setAssociatedRetainedObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) {
|
||||
|
||||
objc_setAssociatedObject(object, key, associatedObject, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
|
||||
}
|
||||
|
||||
internal func setAssociatedCopiedObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) {
|
||||
|
||||
objc_setAssociatedObject(object, key, associatedObject, UInt(OBJC_ASSOCIATION_COPY_NONATOMIC))
|
||||
}
|
||||
|
||||
internal func setAssociatedAssignedObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) {
|
||||
|
||||
objc_setAssociatedObject(object, key, associatedObject, UInt(OBJC_ASSOCIATION_ASSIGN))
|
||||
}
|
||||
|
||||
internal func setAssociatedWeakObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) {
|
||||
|
||||
if let associatedObject = associatedObject {
|
||||
|
||||
objc_setAssociatedObject(object, key, WeakObject(associatedObject), UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
|
||||
}
|
||||
else {
|
||||
|
||||
objc_setAssociatedObject(object, key, nil, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
|
||||
}
|
||||
}
|
||||
91
CoreStore/Internal/NSManagedObject+Transaction.swift
Normal file
91
CoreStore/Internal/NSManagedObject+Transaction.swift
Normal file
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// NSManagedObject+Transaction.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright (c) 2014 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - NSManagedObject
|
||||
|
||||
internal extension NSManagedObject {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal class func createInContext(context: NSManagedObjectContext) -> Self {
|
||||
|
||||
return self(
|
||||
entity: context.entityDescriptionForEntityClass(self)!,
|
||||
insertIntoManagedObjectContext: context
|
||||
)
|
||||
}
|
||||
|
||||
internal func inContext(context: NSManagedObjectContext) -> Self? {
|
||||
|
||||
return self.typedObjectInContext(context)
|
||||
}
|
||||
|
||||
internal func deleteFromContext() {
|
||||
|
||||
self.managedObjectContext?.deleteObject(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private func typedObjectInContext<T: NSManagedObject>(context: NSManagedObjectContext) -> T? {
|
||||
|
||||
let objectID = self.objectID
|
||||
if objectID.temporaryID {
|
||||
|
||||
var error: NSError?
|
||||
var didSucceed: Bool?
|
||||
if let managedObjectContext = self.managedObjectContext {
|
||||
|
||||
managedObjectContext.performBlockAndWait {
|
||||
|
||||
didSucceed = managedObjectContext.obtainPermanentIDsForObjects([self], error: &error)
|
||||
}
|
||||
}
|
||||
if didSucceed != true {
|
||||
|
||||
CoreStore.handleError(
|
||||
error ?? NSError(coreStoreErrorCode: .UnknownError),
|
||||
"Failed to obtain permanent ID for object.")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var error: NSError?
|
||||
if let existingObject = context.existingObjectWithID(objectID, error: &error) {
|
||||
|
||||
return (existingObject as! T)
|
||||
}
|
||||
|
||||
CoreStore.handleError(
|
||||
error ?? NSError(coreStoreErrorCode: .UnknownError),
|
||||
"Failed to load existing <\(T.self)> in context.")
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
131
CoreStore/Internal/NSManagedObjectContext+CoreStore.swift
Normal file
131
CoreStore/Internal/NSManagedObjectContext+CoreStore.swift
Normal file
@@ -0,0 +1,131 @@
|
||||
//
|
||||
// NSManagedObjectContext+CoreStore.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright (c) 2014 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
import GCDKit
|
||||
|
||||
|
||||
// MARK: - NSManagedObjectContext
|
||||
|
||||
internal extension NSManagedObjectContext {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal var shouldCascadeSavesToParent: Bool {
|
||||
|
||||
get {
|
||||
|
||||
let number: NSNumber? = getAssociatedObjectForKey(
|
||||
&PropertyKeys.shouldCascadeSavesToParent,
|
||||
inObject: self
|
||||
)
|
||||
return number?.boolValue ?? false
|
||||
}
|
||||
set {
|
||||
|
||||
setAssociatedCopiedObject(
|
||||
NSNumber(bool: newValue),
|
||||
forKey: &PropertyKeys.shouldCascadeSavesToParent,
|
||||
inObject: self
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal func entityDescriptionForEntityClass(entity: NSManagedObject.Type) -> NSEntityDescription? {
|
||||
|
||||
if let entityName = self.parentStack?.entityNameForEntityClass(entity) {
|
||||
|
||||
return NSEntityDescription.entityForName(
|
||||
entityName,
|
||||
inManagedObjectContext: self
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
internal func setupForCoreStoreWithContextName(contextName: String) {
|
||||
|
||||
if self.respondsToSelector("setName:") {
|
||||
|
||||
self.name = contextName
|
||||
}
|
||||
|
||||
self.observerForWillSaveNotification = NotificationObserver(
|
||||
notificationName: NSManagedObjectContextWillSaveNotification,
|
||||
object: self,
|
||||
closure: { (note) -> Void in
|
||||
|
||||
let context = note.object as! NSManagedObjectContext
|
||||
let insertedObjects = context.insertedObjects
|
||||
let numberOfInsertedObjects = insertedObjects.count
|
||||
if numberOfInsertedObjects <= 0 {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var error: NSError?
|
||||
if context.obtainPermanentIDsForObjects(Array(insertedObjects), error: &error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
CoreStore.handleError(
|
||||
error ?? NSError(coreStoreErrorCode: .UnknownError),
|
||||
"Failed to obtain permanent ID(s) for \(numberOfInsertedObjects) inserted object(s)."
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private struct PropertyKeys {
|
||||
|
||||
static var observerForWillSaveNotification: Void?
|
||||
static var shouldCascadeSavesToParent: Void?
|
||||
}
|
||||
|
||||
private var observerForWillSaveNotification: NotificationObserver? {
|
||||
|
||||
get {
|
||||
|
||||
return getAssociatedObjectForKey(
|
||||
&PropertyKeys.observerForWillSaveNotification,
|
||||
inObject: self
|
||||
)
|
||||
}
|
||||
set {
|
||||
|
||||
setAssociatedRetainedObject(
|
||||
newValue,
|
||||
forKey: &PropertyKeys.observerForWillSaveNotification,
|
||||
inObject: self
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
330
CoreStore/Internal/NSManagedObjectContext+Querying.swift
Normal file
330
CoreStore/Internal/NSManagedObjectContext+Querying.swift
Normal file
@@ -0,0 +1,330 @@
|
||||
//
|
||||
// NSManagedObjectContext+Querying.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright (c) 2015 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - NSManagedObjectContext
|
||||
|
||||
internal extension NSManagedObjectContext {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
internal func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
|
||||
return self.fetchOne(from, fetchClauses)
|
||||
}
|
||||
|
||||
internal func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
|
||||
let fetchRequest = NSFetchRequest()
|
||||
from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
fetchRequest.fetchLimit = 1
|
||||
fetchRequest.resultType = .ManagedObjectResultType
|
||||
|
||||
for clause in fetchClauses {
|
||||
|
||||
clause.applyToFetchRequest(fetchRequest)
|
||||
}
|
||||
|
||||
var fetchResults: [T]?
|
||||
var error: NSError?
|
||||
self.performBlockAndWait {
|
||||
|
||||
fetchResults = self.executeFetchRequest(fetchRequest, error: &error) as? [T]
|
||||
}
|
||||
if fetchResults == nil {
|
||||
|
||||
CoreStore.handleError(
|
||||
error ?? NSError(coreStoreErrorCode: .UnknownError),
|
||||
"Failed executing fetch request.")
|
||||
return nil
|
||||
}
|
||||
|
||||
return fetchResults?.first
|
||||
}
|
||||
|
||||
internal func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
|
||||
return self.fetchAll(from, fetchClauses)
|
||||
}
|
||||
|
||||
internal func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
|
||||
let fetchRequest = NSFetchRequest()
|
||||
from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
fetchRequest.fetchLimit = 0
|
||||
fetchRequest.resultType = .ManagedObjectResultType
|
||||
|
||||
for clause in fetchClauses {
|
||||
|
||||
clause.applyToFetchRequest(fetchRequest)
|
||||
}
|
||||
|
||||
var fetchResults: [T]?
|
||||
var error: NSError?
|
||||
self.performBlockAndWait {
|
||||
|
||||
fetchResults = self.executeFetchRequest(fetchRequest, error: &error) as? [T]
|
||||
}
|
||||
if fetchResults == nil {
|
||||
|
||||
CoreStore.handleError(
|
||||
error ?? NSError(coreStoreErrorCode: .UnknownError),
|
||||
"Failed executing fetch request.")
|
||||
return nil
|
||||
}
|
||||
|
||||
return fetchResults
|
||||
}
|
||||
|
||||
internal func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
|
||||
return self.fetchCount(from, fetchClauses)
|
||||
}
|
||||
|
||||
internal func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
|
||||
let fetchRequest = NSFetchRequest()
|
||||
from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
for clause in fetchClauses {
|
||||
|
||||
clause.applyToFetchRequest(fetchRequest)
|
||||
}
|
||||
|
||||
var count = 0
|
||||
var error: NSError?
|
||||
self.performBlockAndWait {
|
||||
|
||||
count = self.countForFetchRequest(fetchRequest, error: &error)
|
||||
}
|
||||
if count == NSNotFound {
|
||||
|
||||
CoreStore.handleError(
|
||||
error ?? NSError(coreStoreErrorCode: .UnknownError),
|
||||
"Failed executing fetch request.")
|
||||
return nil
|
||||
}
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
internal func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
|
||||
return self.fetchObjectID(from, fetchClauses)
|
||||
}
|
||||
|
||||
internal func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
|
||||
let fetchRequest = NSFetchRequest()
|
||||
from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
fetchRequest.fetchLimit = 1
|
||||
fetchRequest.resultType = .ManagedObjectIDResultType
|
||||
|
||||
for clause in fetchClauses {
|
||||
|
||||
clause.applyToFetchRequest(fetchRequest)
|
||||
}
|
||||
|
||||
var fetchResults: [NSManagedObjectID]?
|
||||
var error: NSError?
|
||||
self.performBlockAndWait {
|
||||
|
||||
fetchResults = self.executeFetchRequest(fetchRequest, error: &error) as? [NSManagedObjectID]
|
||||
}
|
||||
if fetchResults == nil {
|
||||
|
||||
CoreStore.handleError(
|
||||
error ?? NSError(coreStoreErrorCode: .UnknownError),
|
||||
"Failed executing fetch request.")
|
||||
return nil
|
||||
}
|
||||
|
||||
return fetchResults?.first
|
||||
}
|
||||
|
||||
internal func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
|
||||
return self.fetchObjectIDs(from, fetchClauses)
|
||||
}
|
||||
|
||||
internal func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
|
||||
let fetchRequest = NSFetchRequest()
|
||||
from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
fetchRequest.fetchLimit = 0
|
||||
fetchRequest.resultType = .ManagedObjectIDResultType
|
||||
|
||||
for clause in fetchClauses {
|
||||
|
||||
clause.applyToFetchRequest(fetchRequest)
|
||||
}
|
||||
|
||||
var fetchResults: [NSManagedObjectID]?
|
||||
var error: NSError?
|
||||
self.performBlockAndWait {
|
||||
|
||||
fetchResults = self.executeFetchRequest(fetchRequest, error: &error) as? [NSManagedObjectID]
|
||||
}
|
||||
if fetchResults == nil {
|
||||
|
||||
CoreStore.handleError(
|
||||
error ?? NSError(coreStoreErrorCode: .UnknownError),
|
||||
"Failed executing fetch request.")
|
||||
return nil
|
||||
}
|
||||
|
||||
return fetchResults
|
||||
}
|
||||
|
||||
internal func deleteAll<T: NSManagedObject>(from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
|
||||
|
||||
return self.deleteAll(from, deleteClauses)
|
||||
}
|
||||
|
||||
internal func deleteAll<T: NSManagedObject>(from: From<T>, _ deleteClauses: [DeleteClause]) -> Int? {
|
||||
|
||||
let fetchRequest = NSFetchRequest()
|
||||
from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
fetchRequest.fetchLimit = 0
|
||||
fetchRequest.resultType = .ManagedObjectResultType
|
||||
fetchRequest.returnsObjectsAsFaults = true
|
||||
|
||||
for clause in deleteClauses {
|
||||
|
||||
clause.applyToFetchRequest(fetchRequest)
|
||||
}
|
||||
|
||||
var numberOfDeletedObjects: Int?
|
||||
var error: NSError?
|
||||
self.performBlockAndWait {
|
||||
|
||||
autoreleasepool {
|
||||
|
||||
if let fetchResults = self.executeFetchRequest(fetchRequest, error: &error) as? [T] {
|
||||
|
||||
numberOfDeletedObjects = fetchResults.count
|
||||
for object in fetchResults {
|
||||
|
||||
self.deleteObject(object)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if numberOfDeletedObjects == nil {
|
||||
|
||||
CoreStore.handleError(
|
||||
error ?? NSError(coreStoreErrorCode: .UnknownError),
|
||||
"Failed executing fetch request.")
|
||||
return nil
|
||||
}
|
||||
|
||||
return numberOfDeletedObjects
|
||||
}
|
||||
|
||||
internal func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
|
||||
return self.queryValue(from, selectClause, queryClauses)
|
||||
}
|
||||
|
||||
internal func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
|
||||
let fetchRequest = NSFetchRequest()
|
||||
from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
fetchRequest.fetchLimit = 0
|
||||
|
||||
selectClause.applyToFetchRequest(fetchRequest)
|
||||
|
||||
for clause in queryClauses {
|
||||
|
||||
clause.applyToFetchRequest(fetchRequest)
|
||||
}
|
||||
|
||||
var fetchResults: [AnyObject]?
|
||||
var error: NSError?
|
||||
self.performBlockAndWait {
|
||||
|
||||
fetchResults = self.executeFetchRequest(fetchRequest, error: &error)
|
||||
}
|
||||
if let fetchResults = fetchResults {
|
||||
|
||||
if let rawResult = fetchResults.first as? NSDictionary,
|
||||
let rawObject: AnyObject = rawResult[selectClause.keyPathForFirstSelectTerm()] {
|
||||
|
||||
return Select<U>.ReturnType.fromResultObject(rawObject)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
CoreStore.handleError(
|
||||
error ?? NSError(coreStoreErrorCode: .UnknownError),
|
||||
"Failed executing fetch request.")
|
||||
return nil
|
||||
}
|
||||
|
||||
internal func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? {
|
||||
|
||||
return self.queryAttributes(from, selectClause, queryClauses)
|
||||
}
|
||||
|
||||
internal func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {
|
||||
|
||||
let fetchRequest = NSFetchRequest()
|
||||
from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
fetchRequest.fetchLimit = 0
|
||||
|
||||
selectClause.applyToFetchRequest(fetchRequest)
|
||||
|
||||
for clause in queryClauses {
|
||||
|
||||
clause.applyToFetchRequest(fetchRequest)
|
||||
}
|
||||
|
||||
var fetchResults: [AnyObject]?
|
||||
var error: NSError?
|
||||
self.performBlockAndWait {
|
||||
|
||||
fetchResults = self.executeFetchRequest(fetchRequest, error: &error)
|
||||
}
|
||||
if let fetchResults = fetchResults {
|
||||
|
||||
return Select<NSDictionary>.ReturnType.fromResultObjects(fetchResults)
|
||||
}
|
||||
|
||||
CoreStore.handleError(
|
||||
error ?? NSError(coreStoreErrorCode: .UnknownError),
|
||||
"Failed executing fetch request.")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
123
CoreStore/Internal/NSManagedObjectContext+Setup.swift
Normal file
123
CoreStore/Internal/NSManagedObjectContext+Setup.swift
Normal file
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// NSManagedObjectContext+Setup.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright (c) 2015 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - NSManagedObjectContext
|
||||
|
||||
internal extension NSManagedObjectContext {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal weak var parentStack: DataStack? {
|
||||
|
||||
get {
|
||||
|
||||
if let parentContext = self.parentContext {
|
||||
|
||||
return parentContext.parentStack
|
||||
}
|
||||
|
||||
return getAssociatedObjectForKey(&PropertyKeys.parentStack, inObject: self)
|
||||
}
|
||||
set {
|
||||
|
||||
if self.parentContext != nil {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
setAssociatedWeakObject(
|
||||
newValue,
|
||||
forKey: &PropertyKeys.parentStack,
|
||||
inObject: self
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal class func rootSavingContextForCoordinator(coordinator: NSPersistentStoreCoordinator) -> NSManagedObjectContext {
|
||||
|
||||
let context = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
|
||||
context.persistentStoreCoordinator = coordinator
|
||||
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
||||
context.undoManager = nil
|
||||
context.setupForCoreStoreWithContextName("com.corestore.rootcontext")
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
internal class func mainContextForRootContext(rootContext: NSManagedObjectContext) -> NSManagedObjectContext {
|
||||
|
||||
let context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
|
||||
context.parentContext = rootContext
|
||||
context.shouldCascadeSavesToParent = true
|
||||
context.undoManager = nil
|
||||
context.setupForCoreStoreWithContextName("com.corestore.maincontext")
|
||||
context.observerForDidSaveNotification = NotificationObserver(
|
||||
notificationName: NSManagedObjectContextDidSaveNotification,
|
||||
object: rootContext,
|
||||
closure: { [weak context] (note) -> Void in
|
||||
|
||||
context?.performBlockAndWait { () -> Void in
|
||||
|
||||
context?.mergeChangesFromContextDidSaveNotification(note)
|
||||
}
|
||||
return
|
||||
}
|
||||
)
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private struct PropertyKeys {
|
||||
|
||||
static var parentStack: Void?
|
||||
static var observerForDidSaveNotification: Void?
|
||||
}
|
||||
|
||||
private var observerForDidSaveNotification: NotificationObserver? {
|
||||
|
||||
get {
|
||||
|
||||
return getAssociatedObjectForKey(
|
||||
&PropertyKeys.observerForDidSaveNotification,
|
||||
inObject: self
|
||||
)
|
||||
}
|
||||
set {
|
||||
|
||||
setAssociatedRetainedObject(
|
||||
newValue,
|
||||
forKey: &PropertyKeys.observerForDidSaveNotification,
|
||||
inObject: self
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
188
CoreStore/Internal/NSManagedObjectContext+Transaction.swift
Normal file
188
CoreStore/Internal/NSManagedObjectContext+Transaction.swift
Normal file
@@ -0,0 +1,188 @@
|
||||
//
|
||||
// NSManagedObjectContext+Transaction.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright (c) 2015 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
import GCDKit
|
||||
|
||||
|
||||
// MARK: - NSManagedObjectContext
|
||||
|
||||
internal extension NSManagedObjectContext {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal weak var parentTransaction: BaseDataTransaction? {
|
||||
|
||||
get {
|
||||
|
||||
return getAssociatedObjectForKey(
|
||||
&PropertyKeys.parentTransaction,
|
||||
inObject: self
|
||||
)
|
||||
}
|
||||
set {
|
||||
|
||||
setAssociatedWeakObject(
|
||||
newValue,
|
||||
forKey: &PropertyKeys.parentTransaction,
|
||||
inObject: self
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal func temporaryContextInTransactionWithConcurrencyType(concurrencyType: NSManagedObjectContextConcurrencyType) -> NSManagedObjectContext {
|
||||
|
||||
let context = NSManagedObjectContext(concurrencyType: concurrencyType)
|
||||
context.parentContext = self
|
||||
context.parentStack = self.parentStack
|
||||
context.setupForCoreStoreWithContextName("com.corestore.temporarycontext")
|
||||
context.shouldCascadeSavesToParent = (self.parentStack?.rootSavingContext == self)
|
||||
context.retainsRegisteredObjects = true
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
internal func saveSynchronously() -> SaveResult {
|
||||
|
||||
var result = SaveResult(hasChanges: false)
|
||||
self.performBlockAndWait {
|
||||
[unowned self] () -> Void in
|
||||
|
||||
if !self.hasChanges {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var saveError: NSError?
|
||||
if self.save(&saveError) {
|
||||
|
||||
if self.shouldCascadeSavesToParent {
|
||||
|
||||
if let parentContext = self.parentContext {
|
||||
|
||||
switch parentContext.saveSynchronously() {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
result = SaveResult(hasChanges: true)
|
||||
case .Failure(let error):
|
||||
result = SaveResult(error)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
result = SaveResult(hasChanges: true)
|
||||
}
|
||||
else if let error = saveError {
|
||||
|
||||
CoreStore.handleError(
|
||||
error,
|
||||
"Failed to save <\(NSManagedObjectContext.self)>.")
|
||||
result = SaveResult(error)
|
||||
}
|
||||
else {
|
||||
|
||||
result = SaveResult(hasChanges: false)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
internal func saveAsynchronouslyWithCompletion(completion: ((result: SaveResult) -> Void)?) {
|
||||
|
||||
self.performBlock { () -> Void in
|
||||
|
||||
if !self.hasChanges {
|
||||
|
||||
if let completion = completion {
|
||||
|
||||
GCDQueue.Main.async {
|
||||
|
||||
completion(result: SaveResult(hasChanges: false))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var saveError: NSError?
|
||||
if self.save(&saveError) {
|
||||
|
||||
if self.shouldCascadeSavesToParent {
|
||||
|
||||
if let parentContext = self.parentContext {
|
||||
|
||||
let result = parentContext.saveSynchronously()
|
||||
if let completion = completion {
|
||||
|
||||
GCDQueue.Main.async {
|
||||
|
||||
completion(result: result)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if let completion = completion {
|
||||
|
||||
GCDQueue.Main.async {
|
||||
|
||||
completion(result: SaveResult(hasChanges: true))
|
||||
}
|
||||
}
|
||||
}
|
||||
else if let error = saveError {
|
||||
|
||||
CoreStore.handleError(
|
||||
error,
|
||||
"Failed to save <\(NSManagedObjectContext.self)>.")
|
||||
if let completion = completion {
|
||||
|
||||
GCDQueue.Main.async {
|
||||
|
||||
completion(result: SaveResult(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
else if let completion = completion {
|
||||
|
||||
GCDQueue.Main.async {
|
||||
|
||||
completion(result: SaveResult(hasChanges: false))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private struct PropertyKeys {
|
||||
|
||||
static var parentTransaction: Void?
|
||||
}
|
||||
}
|
||||
59
CoreStore/Internal/NotificationObserver.swift
Normal file
59
CoreStore/Internal/NotificationObserver.swift
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// NotificationObserver.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright (c) 2014 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - NotificationObserver
|
||||
|
||||
internal final class NotificationObserver {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
let notificationName: String
|
||||
let object: AnyObject?
|
||||
let observer: NSObjectProtocol
|
||||
|
||||
init(notificationName: String, object: AnyObject?, closure: (note: NSNotification!) -> Void) {
|
||||
|
||||
self.notificationName = notificationName
|
||||
self.object = object
|
||||
self.observer = NSNotificationCenter.defaultCenter().addObserverForName(
|
||||
notificationName,
|
||||
object: object,
|
||||
queue: nil,
|
||||
usingBlock: closure
|
||||
)
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
||||
NSNotificationCenter.defaultCenter().removeObserver(
|
||||
self.observer,
|
||||
name: self.notificationName,
|
||||
object: self.object
|
||||
)
|
||||
}
|
||||
}
|
||||
44
CoreStore/Internal/WeakObject.swift
Normal file
44
CoreStore/Internal/WeakObject.swift
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// WeakObject.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright (c) 2015 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - WeakObject
|
||||
|
||||
internal final class WeakObject {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal init(_ object: AnyObject) {
|
||||
|
||||
self.object = object
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private(set) weak var object: AnyObject?
|
||||
}
|
||||
Reference in New Issue
Block a user