Merge branch 'swift3_develop' into develop

# Conflicts:
#	.travis.yml
#	CoreStore.podspec
#	CoreStore.xcodeproj/project.pbxproj
#	Sources/Info.plist
This commit is contained in:
John Estropia
2017-01-06 16:03:28 +09:00
162 changed files with 6807 additions and 6464 deletions

View File

@@ -0,0 +1,41 @@
//
// CoreStoreFetchRequest+CoreStore.swift
// CoreStore
//
// Copyright © 2016 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: - CoreStoreFetchRequest
internal extension CoreStoreFetchRequest {
// MARK: Internal
@nonobjc
internal func dynamicCast<U: NSFetchRequestResult>() -> NSFetchRequest<U> {
return unsafeBitCast(self, to: NSFetchRequest<U>.self)
}
}

View File

@@ -31,12 +31,12 @@ import CoreData
// MARK: - CoreStoreFetchedResultsController
internal final class CoreStoreFetchedResultsController: NSFetchedResultsController {
internal final class CoreStoreFetchedResultsController: NSFetchedResultsController<NSManagedObject> {
// MARK: Internal
@nonobjc
internal convenience init<T: NSManagedObject>(dataStack: DataStack, fetchRequest: NSFetchRequest, from: From<T>? = nil, sectionBy: SectionBy? = nil, applyFetchClauses: (fetchRequest: NSFetchRequest) -> Void) {
internal convenience init<T: NSManagedObject>(dataStack: DataStack, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>? = nil, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
self.init(
context: dataStack.mainContext,
@@ -48,14 +48,14 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
}
@nonobjc
internal init<T: NSManagedObject>(context: NSManagedObjectContext, fetchRequest: NSFetchRequest, from: From<T>? = nil, sectionBy: SectionBy? = nil, applyFetchClauses: (fetchRequest: NSFetchRequest) -> Void) {
internal init<T: NSManagedObject>(context: NSManagedObjectContext, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>? = nil, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
_ = from?.applyToFetchRequest(
fetchRequest,
context: context,
applyAffectedStores: false
)
applyFetchClauses(fetchRequest: fetchRequest)
applyFetchClauses(fetchRequest)
if let from = from {
@@ -68,7 +68,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
guard let from = (fetchRequest.entity.flatMap { $0.managedObjectClassName }).flatMap(NSClassFromString).flatMap(From.init) else {
CoreStore.abort("Attempted to create an \(cs_typeName(NSFetchedResultsController)) without a \(cs_typeName(From)) clause or an \(cs_typeName(NSEntityDescription)).")
CoreStore.abort("Attempted to create a \(CoreStoreFetchedResultsController.self) without a \(cs_typeName(From<T>.self)) clause or an \(cs_typeName(NSEntityDescription.self)).")
}
self.reapplyAffectedStores = { fetchRequest, context in
@@ -88,16 +88,22 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
@nonobjc
internal func performFetchFromSpecifiedStores() throws {
if !self.reapplyAffectedStores(fetchRequest: self.fetchRequest, context: self.managedObjectContext) {
if !self.reapplyAffectedStores(self.fetchRequest, self.managedObjectContext) {
CoreStore.log(
.Warning,
message: "Attempted to perform a fetch on an \(cs_typeName(NSFetchedResultsController)) but could not find any persistent store for the entity \(cs_typeName(self.fetchRequest.entityName))"
.warning,
message: "Attempted to perform a fetch on an \(cs_typeName(self)) but could not find any persistent store for the entity \(cs_typeName(self.fetchRequest.entityName))"
)
}
try self.performFetch()
}
@nonobjc
internal func dynamicCast<U: NSFetchRequestResult>() -> NSFetchedResultsController<U> {
return unsafeBitCast(self, to: NSFetchedResultsController<U>.self)
}
deinit {
self.delegate = nil
@@ -107,7 +113,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
// MARK: Private
@nonobjc
private let reapplyAffectedStores: (fetchRequest: NSFetchRequest, context: NSManagedObjectContext) -> Bool
private let reapplyAffectedStores: (_ fetchRequest: NSFetchRequest<NSManagedObject>, _ context: NSManagedObjectContext) -> Bool
}
#endif

View File

@@ -0,0 +1,97 @@
//
// DispatchQueue+CoreStore.swift
// CoreStore
//
// Copyright © 2016 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: - DispatchQueue
internal extension DispatchQueue {
@nonobjc
internal static func serial(_ label: String, qos: DispatchQoS = .default) -> DispatchQueue {
return DispatchQueue(
label: label,
qos: qos,
attributes: [],
autoreleaseFrequency: .inherit,
target: nil
)
}
@nonobjc
internal static func concurrent(_ label: String, qos: DispatchQoS = .default) -> DispatchQueue {
return DispatchQueue(
label: label,
qos: qos,
attributes: .concurrent,
autoreleaseFrequency: .inherit,
target: nil
)
}
@nonobjc
internal func cs_isCurrentExecutionContext() -> Bool {
let specific = ObjectIdentifier(self)
self.setSpecific(key: Static.specificKey, value: specific)
return DispatchQueue.getSpecific(key: Static.specificKey) == specific
}
@nonobjc
internal func cs_sync<T>(_ closure: () throws -> T) rethrows -> T {
return try self.sync { try autoreleasepool(invoking: closure) }
}
@nonobjc
internal func cs_async(_ closure: @escaping () -> Void) {
self.async { autoreleasepool(invoking: closure) }
}
@nonobjc
internal func cs_barrierSync<T>(_ closure: () throws -> T) rethrows -> T {
return try self.sync(flags: .barrier) { try autoreleasepool(invoking: closure) }
}
@nonobjc
internal func cs_barrierAsync(_ closure: @escaping () -> Void) {
self.async(flags: .barrier) { autoreleasepool(invoking: closure) }
}
// MARK: Private
private enum Static {
static let specificKey = DispatchSpecificKey<ObjectIdentifier>()
}
}

View File

@@ -33,21 +33,21 @@ import CoreData
internal protocol FetchedResultsControllerHandler: class {
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?)
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeObject anObject: Any, atIndexPath indexPath: IndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: IndexPath?)
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType)
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType)
func controllerWillChangeContent(controller: NSFetchedResultsController)
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
func controllerDidChangeContent(controller: NSFetchedResultsController)
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String?) -> String?
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, sectionIndexTitleForSectionName sectionName: String?) -> String?
}
// MARK: - FetchedResultsControllerDelegate
internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResultsControllerDelegate {
internal final class FetchedResultsControllerDelegate<EntityType: NSManagedObject>: NSObject, NSFetchedResultsControllerDelegate {
// MARK: Internal
@@ -58,7 +58,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
internal weak var handler: FetchedResultsControllerHandler?
@nonobjc
internal weak var fetchedResultsController: NSFetchedResultsController? {
internal weak var fetchedResultsController: CoreStoreFetchedResultsController? {
didSet {
@@ -76,7 +76,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
// MARK: NSFetchedResultsControllerDelegate
@objc
dynamic func controllerWillChangeContent(controller: NSFetchedResultsController) {
dynamic func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
guard self.enabled else {
@@ -90,7 +90,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
}
@objc
dynamic func controllerDidChangeContent(controller: NSFetchedResultsController) {
dynamic func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
guard self.enabled else {
@@ -101,7 +101,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
}
@objc
dynamic func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
dynamic func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
guard self.enabled else {
@@ -120,21 +120,32 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
// http://stackoverflow.com/questions/31383760/ios-9-attempt-to-delete-and-reload-the-same-index-path/31384014#31384014
// https://forums.developer.apple.com/message/9998#9998
// https://forums.developer.apple.com/message/31849#31849
if #available(iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
// I don't know if iOS 10 even attempted to fix this mess...
if case .update = actualType,
indexPath != nil,
newIndexPath != nil {
actualType = .move
}
}
if #available(iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
// I don't know if iOS 10 even attempted to fix this mess...
if case .Update = actualType
where indexPath != nil && newIndexPath != nil {
if case .update = actualType,
indexPath != nil && newIndexPath != nil {
actualType = .Move
actualType = .move
}
}
switch actualType {
case .Update:
guard let section = indexPath?.indexAtPosition(0) else {
case .update:
guard let section = indexPath?[0] else {
return
}
@@ -144,7 +155,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
return
}
case .Move:
case .move:
guard let indexPath = indexPath, let newIndexPath = newIndexPath else {
return
@@ -153,25 +164,25 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
break
}
if self.insertedSections.contains(indexPath.indexAtPosition(0)) {
if self.insertedSections.contains(indexPath[0]) {
// Observers that handle the .Move change are advised to delete then reinsert the object instead of just moving. This is especially true when indexPath and newIndexPath are equal. For example, calling tableView.moveRowAtIndexPath(_:toIndexPath) when both indexPaths are the same will crash the tableView.
self.handler?.controller(
controller,
didChangeObject: anObject,
atIndexPath: indexPath,
forChangeType: .Move,
forChangeType: .move,
newIndexPath: newIndexPath
)
return
}
if self.deletedSections.contains(indexPath.indexAtPosition(0)) {
if self.deletedSections.contains(indexPath[0]) {
self.handler?.controller(
controller,
didChangeObject: anObject,
atIndexPath: nil,
forChangeType: .Insert,
forChangeType: .insert,
newIndexPath: indexPath
)
return
@@ -180,7 +191,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
controller,
didChangeObject: anObject,
atIndexPath: indexPath,
forChangeType: .Update,
forChangeType: .update,
newIndexPath: nil
)
return
@@ -199,7 +210,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
}
@objc
dynamic func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
dynamic func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
guard self.enabled else {
@@ -208,8 +219,8 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
switch type {
case .Delete: self.deletedSections.insert(sectionIndex)
case .Insert: self.insertedSections.insert(sectionIndex)
case .delete: self.deletedSections.insert(sectionIndex)
case .insert: self.insertedSections.insert(sectionIndex)
default: break
}
@@ -222,7 +233,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
}
@objc
dynamic func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String) -> String? {
dynamic func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, sectionIndexTitleForSectionName sectionName: String) -> String? {
return self.handler?.controller(
controller,

View File

@@ -25,70 +25,9 @@
import Foundation
// MARK: Associated Objects
// MARK: - Custom AutoreleasePool
internal func cs_autoreleasepool(@noescape closure: () -> Void) {
autoreleasepool(closure)
}
internal func cs_autoreleasepool<T>(@noescape closure: () -> T) -> T {
var closureValue: T!
autoreleasepool {
closureValue = closure()
}
return closureValue
}
internal func cs_autoreleasepool<T>(@noescape closure: () throws -> T) throws -> T {
var closureValue: T!
var closureError: ErrorType?
autoreleasepool {
do {
closureValue = try closure()
}
catch {
closureError = error
}
}
if let closureError = closureError {
throw closureError
}
return closureValue
}
internal func cs_autoreleasepool(@noescape closure: () throws -> Void) throws {
var closureError: ErrorType?
autoreleasepool {
do {
try closure()
}
catch {
closureError = error
}
}
if let closureError = closureError {
throw closureError
}
}
internal func cs_getAssociatedObjectForKey<T: AnyObject>(key: UnsafePointer<Void>, inObject object: AnyObject) -> T? {
internal func cs_getAssociatedObjectForKey<T: AnyObject>(_ key: UnsafeRawPointer, inObject object: Any) -> T? {
switch objc_getAssociatedObject(object, key) {
@@ -103,17 +42,17 @@ internal func cs_getAssociatedObjectForKey<T: AnyObject>(key: UnsafePointer<Void
}
}
internal func cs_setAssociatedRetainedObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) {
internal func cs_setAssociatedRetainedObject<T: AnyObject>(_ associatedObject: T?, forKey key: UnsafeRawPointer, inObject object: Any) {
objc_setAssociatedObject(object, key, associatedObject, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
internal func cs_setAssociatedCopiedObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) {
internal func cs_setAssociatedCopiedObject<T: AnyObject>(_ associatedObject: T?, forKey key: UnsafeRawPointer, inObject object: Any) {
objc_setAssociatedObject(object, key, associatedObject, .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
internal func cs_setAssociatedWeakObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) {
internal func cs_setAssociatedWeakObject<T: AnyObject>(_ associatedObject: T?, forKey key: UnsafeRawPointer, inObject object: Any) {
if let associatedObject = associatedObject {
@@ -128,22 +67,27 @@ internal func cs_setAssociatedWeakObject<T: AnyObject>(associatedObject: T?, for
// MARK: Printing Utilities
internal func cs_typeName<T>(value: T) -> String {
internal func cs_typeName<T>(_ value: T) -> String {
return "'\(String(reflecting: value.dynamicType))'"
return "'\(String(reflecting: type(of: value)))'"
}
internal func cs_typeName<T>(value: T.Type) -> String {
internal func cs_typeName<T>(_ value: T.Type) -> String {
return "'\(value)'"
}
internal func cs_typeName(value: AnyClass) -> String {
internal func cs_typeName(_ value: AnyClass) -> String {
return "'\(value)'"
}
internal func cs_typeName(name: String?) -> String {
internal func cs_typeName(_ name: String) -> String {
return "<\(name)>"
}
internal func cs_typeName(_ name: String?) -> String {
return "<\(name ?? "unknown")>"
}

View File

@@ -29,15 +29,15 @@ import CoreData
// MARK: - MigrationManager
internal final class MigrationManager: NSMigrationManager, NSProgressReporting {
internal final class MigrationManager: NSMigrationManager, ProgressReporting {
// MARK: NSObject
override func didChangeValueForKey(key: String) {
override func didChangeValue(forKey key: String) {
super.didChangeValueForKey(key)
super.didChangeValue(forKey: key)
guard key == "migrationProgress" else {
guard key == #keyPath(NSMigrationManager.migrationProgress) else {
return
}
@@ -48,7 +48,7 @@ internal final class MigrationManager: NSMigrationManager, NSProgressReporting {
// MARK: NSMigrationManager
init(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, progress: NSProgress) {
init(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, progress: Progress) {
self.progress = progress
@@ -56,7 +56,7 @@ internal final class MigrationManager: NSMigrationManager, NSProgressReporting {
}
// MARK: NSProgressReporting
// MARK: ProgressReporting
let progress: NSProgress
let progress: Progress
}

View File

@@ -25,9 +25,6 @@
import Foundation
import CoreData
#if USE_FRAMEWORKS
import GCDKit
#endif
// MARK: - NSManagedObjectContext
@@ -50,7 +47,7 @@ internal extension NSManagedObjectContext {
set {
cs_setAssociatedCopiedObject(
NSNumber(bool: newValue),
NSNumber(value: newValue),
forKey: &PropertyKeys.shouldCascadeSavesToParent,
inObject: self
)
@@ -58,40 +55,30 @@ internal extension NSManagedObjectContext {
}
@nonobjc
internal func entityDescriptionForEntityType(entity: NSManagedObject.Type) -> NSEntityDescription? {
internal func entityDescriptionForEntityType(_ entity: NSManagedObject.Type) -> NSEntityDescription? {
return self.entityDescriptionForEntityClass(entity)
}
@nonobjc
internal func entityDescriptionForEntityClass(entity: AnyClass) -> NSEntityDescription? {
internal func entityDescriptionForEntityClass(_ entity: AnyClass) -> NSEntityDescription? {
guard let entityName = self.parentStack?.entityNameForEntityClass(entity) else {
return nil
}
return NSEntityDescription.entityForName(
entityName,
inManagedObjectContext: self
return NSEntityDescription.entity(
forEntityName: entityName,
in: self
)
}
@nonobjc
internal func setupForCoreStoreWithContextName(contextName: String) {
#if USE_FRAMEWORKS
self.name = contextName
#else
if #available(iOS 8.0, *) {
self.name = contextName
}
#endif
internal func setupForCoreStoreWithContextName(_ contextName: String) {
self.name = contextName
self.observerForWillSaveNotification = NotificationObserver(
notificationName: NSManagedObjectContextWillSaveNotification,
notificationName: NSNotification.Name.NSManagedObjectContextWillSave,
object: self,
closure: { (note) -> Void in
@@ -105,7 +92,7 @@ internal extension NSManagedObjectContext {
do {
try context.obtainPermanentIDsForObjects(Array(insertedObjects))
try context.obtainPermanentIDs(for: Array(insertedObjects))
}
catch {

View File

@@ -29,20 +29,20 @@ import CoreData
// MARK: - NSManagedObjectContext
internal extension NSManagedObjectContext {
extension NSManagedObjectContext: FetchableSource, QueryableSource {
// MARK: Internal: Fetch Existing
// MARK: FetchableSource
@nonobjc
internal func fetchExisting<T: NSManagedObject>(object: T) -> T? {
public func fetchExisting<T: NSManagedObject>(_ object: T) -> T? {
if object.objectID.temporaryID {
if object.objectID.isTemporaryID {
do {
try withExtendedLifetime(self) { (context: NSManagedObjectContext) -> Void in
try context.obtainPermanentIDsForObjects([object])
try context.obtainPermanentIDs(for: [object])
}
}
catch {
@@ -54,10 +54,9 @@ internal extension NSManagedObjectContext {
return nil
}
}
do {
let existingObject = try self.existingObjectWithID(object.objectID)
let existingObject = try self.existingObject(with: object.objectID)
return (existingObject as! T)
}
catch {
@@ -70,125 +69,86 @@ internal extension NSManagedObjectContext {
}
}
// MARK: Internal: Fetch One
@nonobjc
public func fetchExisting<T: NSManagedObject>(_ objectID: NSManagedObjectID) -> T? {
do {
return (try self.existingObject(with: objectID) as! T)
}
catch _ {
return nil
}
}
@nonobjc
internal func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> T? {
public func fetchExisting<T: NSManagedObject, S: Sequence>(_ objects: S) -> [T] where S.Iterator.Element == T {
return objects.flatMap { (try? self.existingObject(with: $0.objectID)) as? T }
}
@nonobjc
public func fetchExisting<T: NSManagedObject, S: Sequence>(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
return objectIDs.flatMap { (try? self.existingObject(with: $0)) as? T }
}
@nonobjc
public func fetchOne<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
return self.fetchOne(from, fetchClauses)
}
@nonobjc
internal func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
public func fetchOne<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
let fetchRequest = CoreStoreFetchRequest()
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
fetchRequest.fetchLimit = 1
fetchRequest.resultType = .ManagedObjectResultType
fetchRequest.resultType = .managedObjectResultType
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
guard storeFound else {
return nil
}
return self.fetchOne(fetchRequest)
return self.fetchOne(fetchRequest.dynamicCast())
}
@nonobjc
internal func fetchOne<T: NSManagedObject>(fetchRequest: NSFetchRequest) -> T? {
var fetchResults: [T]?
var fetchError: ErrorType?
self.performBlockAndWait {
do {
fetchResults = try self.executeFetchRequest(fetchRequest) as? [T]
}
catch {
fetchError = error
}
}
if fetchResults == nil {
CoreStore.log(
CoreStoreError(fetchError),
"Failed executing fetch request."
)
return nil
}
return fetchResults?.first
}
// MARK: Internal: Fetch All
@nonobjc
internal func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
public func fetchAll<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
return self.fetchAll(from, fetchClauses)
}
@nonobjc
internal func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
public func fetchAll<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
let fetchRequest = CoreStoreFetchRequest()
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
fetchRequest.fetchLimit = 0
fetchRequest.resultType = .ManagedObjectResultType
fetchRequest.resultType = .managedObjectResultType
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
guard storeFound else {
return nil
}
return self.fetchAll(fetchRequest)
return self.fetchAll(fetchRequest.dynamicCast())
}
@nonobjc
internal func fetchAll<T: NSManagedObject>(fetchRequest: NSFetchRequest) -> [T]? {
var fetchResults: [T]?
var fetchError: ErrorType?
self.performBlockAndWait {
do {
fetchResults = try self.executeFetchRequest(fetchRequest) as? [T]
}
catch {
fetchError = error
}
}
if fetchResults == nil {
CoreStore.log(
CoreStoreError(fetchError),
"Failed executing fetch request."
)
return nil
}
return fetchResults
}
// MARK: Internal: Count
@nonobjc
internal func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
public func fetchCount<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
return self.fetchCount(from, fetchClauses)
}
@nonobjc
internal func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
public func fetchCount<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
let fetchRequest = CoreStoreFetchRequest()
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
@@ -198,127 +158,65 @@ internal extension NSManagedObjectContext {
return nil
}
return self.fetchCount(fetchRequest)
return self.fetchCount(fetchRequest.dynamicCast())
}
@nonobjc
internal func fetchCount(fetchRequest: NSFetchRequest) -> Int? {
var count = 0
var countError: ErrorType?
self.performBlockAndWait {
do {
count = try self.countForFetchRequest(fetchRequest)
}
catch {
countError = error
}
}
if count == NSNotFound {
CoreStore.log(
CoreStoreError(countError),
"Failed executing fetch request."
)
return nil
}
return count
}
// MARK: Internal: Object ID
@nonobjc
internal func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
public func fetchObjectID<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
return self.fetchObjectID(from, fetchClauses)
}
@nonobjc
internal func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
public func fetchObjectID<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
let fetchRequest = CoreStoreFetchRequest()
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
fetchRequest.fetchLimit = 1
fetchRequest.resultType = .ManagedObjectIDResultType
fetchRequest.resultType = .managedObjectIDResultType
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
guard storeFound else {
return nil
}
return self.fetchObjectID(fetchRequest)
return self.fetchObjectID(fetchRequest.dynamicCast())
}
@nonobjc
internal func fetchObjectID(fetchRequest: NSFetchRequest) -> NSManagedObjectID? {
var fetchResults: [NSManagedObjectID]?
var fetchError: ErrorType?
self.performBlockAndWait {
do {
fetchResults = try self.executeFetchRequest(fetchRequest) as? [NSManagedObjectID]
}
catch {
fetchError = error
}
}
if fetchResults == nil {
CoreStore.log(
CoreStoreError(fetchError),
"Failed executing fetch request."
)
return nil
}
return fetchResults?.first
}
// MARK: Internal: Object IDs
@nonobjc
internal func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
public func fetchObjectIDs<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
return self.fetchObjectIDs(from, fetchClauses)
}
@nonobjc
internal func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
public func fetchObjectIDs<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
let fetchRequest = CoreStoreFetchRequest()
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
fetchRequest.fetchLimit = 0
fetchRequest.resultType = .ManagedObjectIDResultType
fetchRequest.resultType = .managedObjectIDResultType
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
guard storeFound else {
return nil
}
return self.fetchObjectIDs(fetchRequest)
return self.fetchObjectIDs(fetchRequest.dynamicCast())
}
@nonobjc
internal func fetchObjectIDs(fetchRequest: NSFetchRequest) -> [NSManagedObjectID]? {
internal func fetchObjectIDs(_ fetchRequest: NSFetchRequest<NSManagedObjectID>) -> [NSManagedObjectID]? {
var fetchResults: [NSManagedObjectID]?
var fetchError: ErrorType?
self.performBlockAndWait {
var fetchError: Error?
self.performAndWait {
do {
fetchResults = try self.executeFetchRequest(fetchRequest) as? [NSManagedObjectID]
fetchResults = try self.fetch(fetchRequest)
}
catch {
@@ -333,85 +231,20 @@ internal extension NSManagedObjectContext {
)
return nil
}
return fetchResults
}
// MARK: Internal: Delete All
// MARK: QueryableSource
@nonobjc
internal func deleteAll<T: NSManagedObject>(from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
return self.deleteAll(from, deleteClauses)
}
@nonobjc
internal func deleteAll<T: NSManagedObject>(from: From<T>, _ deleteClauses: [DeleteClause]) -> Int? {
let fetchRequest = CoreStoreFetchRequest()
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
fetchRequest.fetchLimit = 0
fetchRequest.resultType = .ManagedObjectResultType
fetchRequest.returnsObjectsAsFaults = true
fetchRequest.includesPropertyValues = false
deleteClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
guard storeFound else {
return nil
}
return self.deleteAll(fetchRequest)
}
@nonobjc
internal func deleteAll(fetchRequest: NSFetchRequest) -> Int? {
var numberOfDeletedObjects: Int?
var fetchError: ErrorType?
self.performBlockAndWait {
cs_autoreleasepool {
do {
let fetchResults = try self.executeFetchRequest(fetchRequest) as? [NSManagedObject] ?? []
for object in fetchResults {
self.deleteObject(object)
}
numberOfDeletedObjects = fetchResults.count
}
catch {
fetchError = error
}
}
}
if numberOfDeletedObjects == nil {
CoreStore.log(
CoreStoreError(fetchError),
"Failed executing fetch request."
)
return nil
}
return numberOfDeletedObjects
}
// MARK: Internal: Value
@nonobjc
internal func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
return self.queryValue(from, selectClause, queryClauses)
}
@nonobjc
internal func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
let fetchRequest = CoreStoreFetchRequest()
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
@@ -430,82 +263,13 @@ internal extension NSManagedObjectContext {
}
@nonobjc
internal func queryValue<U: SelectValueResultType>(selectTerms: [SelectTerm], fetchRequest: NSFetchRequest) -> U? {
var fetchResults: [AnyObject]?
var fetchError: ErrorType?
self.performBlockAndWait {
do {
fetchResults = try self.executeFetchRequest(fetchRequest)
}
catch {
fetchError = error
}
}
if let fetchResults = fetchResults {
if let rawResult = fetchResults.first as? NSDictionary,
let rawObject: AnyObject = rawResult[selectTerms.keyPathForFirstSelectTerm()] {
return Select<U>.ReturnType.fromResultObject(rawObject)
}
return nil
}
CoreStore.log(
CoreStoreError(fetchError),
"Failed executing fetch request."
)
return nil
}
@nonobjc
internal func queryValue(selectTerms: [SelectTerm], fetchRequest: NSFetchRequest) -> AnyObject? {
var fetchResults: [AnyObject]?
var fetchError: ErrorType?
self.performBlockAndWait {
do {
fetchResults = try self.executeFetchRequest(fetchRequest)
}
catch {
fetchError = error
}
}
if let fetchResults = fetchResults {
if let rawResult = fetchResults.first as? NSDictionary,
let rawObject: AnyObject = rawResult[selectTerms.keyPathForFirstSelectTerm()] {
return rawObject
}
return nil
}
CoreStore.log(
CoreStoreError(fetchError),
"Failed executing fetch request."
)
return nil
}
// MARK: Internal: Attributes
@nonobjc
internal func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? {
public func queryAttributes<T: NSManagedObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
return self.queryAttributes(from, selectClause, queryClauses)
}
@nonobjc
internal func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {
public func queryAttributes<T: NSManagedObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
let fetchRequest = CoreStoreFetchRequest()
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
@@ -522,16 +286,210 @@ internal extension NSManagedObjectContext {
return self.queryAttributes(fetchRequest)
}
// MARK: FetchableSource, QueryableSource
@nonobjc
internal func queryAttributes(fetchRequest: NSFetchRequest) -> [[NSString: AnyObject]]? {
public func internalContext() -> NSManagedObjectContext {
var fetchResults: [AnyObject]?
var fetchError: ErrorType?
self.performBlockAndWait {
return self
}
}
// MARK: - NSManagedObjectContext (Internal)
internal extension NSManagedObjectContext {
// MARK: Fetching
@nonobjc
internal func fetchOne<T: NSManagedObject>(_ fetchRequest: NSFetchRequest<T>) -> T? {
var fetchResults: [T]?
var fetchError: Error?
self.performAndWait {
do {
fetchResults = try self.executeFetchRequest(fetchRequest)
fetchResults = try self.fetch(fetchRequest)
}
catch {
fetchError = error
}
}
if fetchResults == nil {
CoreStore.log(
CoreStoreError(fetchError),
"Failed executing fetch request."
)
return nil
}
return fetchResults?.first
}
@nonobjc
internal func fetchAll<T: NSManagedObject>(_ fetchRequest: NSFetchRequest<T>) -> [T]? {
var fetchResults: [T]?
var fetchError: Error?
self.performAndWait {
do {
fetchResults = try self.fetch(fetchRequest)
}
catch {
fetchError = error
}
}
if fetchResults == nil {
CoreStore.log(
CoreStoreError(fetchError),
"Failed executing fetch request."
)
return nil
}
return fetchResults
}
@nonobjc
internal func fetchCount(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) -> Int? {
var count = 0
var countError: Error?
self.performAndWait {
do {
count = try self.count(for: fetchRequest)
}
catch {
countError = error
}
}
if count == NSNotFound {
CoreStore.log(
CoreStoreError(countError),
"Failed executing count request."
)
return nil
}
return count
}
@nonobjc
internal func fetchObjectID(_ fetchRequest: NSFetchRequest<NSManagedObjectID>) -> NSManagedObjectID? {
var fetchResults: [NSManagedObjectID]?
var fetchError: Error?
self.performAndWait {
do {
fetchResults = try self.fetch(fetchRequest)
}
catch {
fetchError = error
}
}
if fetchResults == nil {
CoreStore.log(
CoreStoreError(fetchError),
"Failed executing fetch request."
)
return nil
}
return fetchResults?.first
}
// MARK: Querying
@nonobjc
internal func queryValue<U: SelectValueResultType>(_ selectTerms: [SelectTerm], fetchRequest: NSFetchRequest<NSFetchRequestResult>) -> U? {
var fetchResults: [Any]?
var fetchError: Error?
self.performAndWait {
do {
fetchResults = try self.fetch(fetchRequest)
}
catch {
fetchError = error
}
}
if let fetchResults = fetchResults {
if let rawResult = fetchResults.first as? NSDictionary,
let rawObject = rawResult[selectTerms.keyPathForFirstSelectTerm()] {
return Select<U>.ReturnType.fromResultObject(rawObject)
}
return nil
}
CoreStore.log(
CoreStoreError(fetchError),
"Failed executing fetch request."
)
return nil
}
@nonobjc
internal func queryValue(_ selectTerms: [SelectTerm], fetchRequest: NSFetchRequest<NSFetchRequestResult>) -> Any? {
var fetchResults: [Any]?
var fetchError: Error?
self.performAndWait {
do {
fetchResults = try self.fetch(fetchRequest)
}
catch {
fetchError = error
}
}
if let fetchResults = fetchResults {
if let rawResult = fetchResults.first as? NSDictionary,
let rawObject = rawResult[selectTerms.keyPathForFirstSelectTerm()] {
return rawObject
}
return nil
}
CoreStore.log(
CoreStoreError(fetchError),
"Failed executing fetch request."
)
return nil
}
@nonobjc
internal func queryAttributes(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) -> [[String: Any]]? {
var fetchResults: [Any]?
var fetchError: Error?
self.performAndWait {
do {
fetchResults = try self.fetch(fetchRequest)
}
catch {
@@ -549,4 +507,67 @@ internal extension NSManagedObjectContext {
)
return nil
}
// MARK: Deleting
@nonobjc
internal func deleteAll<T: NSManagedObject>(_ from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
return self.deleteAll(from, deleteClauses)
}
@nonobjc
internal func deleteAll<T: NSManagedObject>(_ from: From<T>, _ deleteClauses: [DeleteClause]) -> Int? {
let fetchRequest = CoreStoreFetchRequest()
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
fetchRequest.fetchLimit = 0
fetchRequest.resultType = .managedObjectResultType
fetchRequest.returnsObjectsAsFaults = true
fetchRequest.includesPropertyValues = false
deleteClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
guard storeFound else {
return nil
}
return self.deleteAll(fetchRequest.dynamicCast())
}
@nonobjc
internal func deleteAll<T: NSManagedObject>(_ fetchRequest: NSFetchRequest<T>) -> Int? {
var numberOfDeletedObjects: Int?
var fetchError: Error?
self.performAndWait {
autoreleasepool {
do {
let fetchResults = try self.fetch(fetchRequest)
for object in fetchResults {
self.delete(object)
}
numberOfDeletedObjects = fetchResults.count
}
catch {
fetchError = error
}
}
}
if numberOfDeletedObjects == nil {
CoreStore.log(
CoreStoreError(fetchError),
"Failed executing fetch request."
)
return nil
}
return numberOfDeletedObjects
}
}

View File

@@ -38,7 +38,7 @@ internal extension NSManagedObjectContext {
get {
if let parentContext = self.parentContext {
if let parentContext = self.parent {
return parentContext.parentStack
}
@@ -47,7 +47,7 @@ internal extension NSManagedObjectContext {
}
set {
guard self.parentContext == nil else {
guard self.parent == nil else {
return
}
@@ -61,9 +61,9 @@ internal extension NSManagedObjectContext {
}
@nonobjc
internal static func rootSavingContextForCoordinator(coordinator: NSPersistentStoreCoordinator) -> NSManagedObjectContext {
internal static func rootSavingContextForCoordinator(_ coordinator: NSPersistentStoreCoordinator) -> NSManagedObjectContext {
let context = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
context.persistentStoreCoordinator = coordinator
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
context.undoManager = nil
@@ -72,18 +72,20 @@ internal extension NSManagedObjectContext {
#if os(iOS) || os(OSX)
context.observerForDidImportUbiquitousContentChangesNotification = NotificationObserver(
notificationName: NSPersistentStoreDidImportUbiquitousContentChangesNotification,
notificationName: NSNotification.Name.NSPersistentStoreDidImportUbiquitousContentChanges,
object: coordinator,
closure: { [weak context] (note) -> Void in
context?.performBlock { () -> Void in
context?.perform { () -> Void in
let updatedObjectIDs = (note.userInfo?[NSUpdatedObjectsKey] as? Set<NSManagedObjectID>) ?? []
for objectID in updatedObjectIDs {
if let updatedObjectIDs = (note.userInfo?[NSUpdatedObjectsKey] as? Set<NSManagedObjectID>) {
context?.objectWithID(objectID).willAccessValueForKey(nil)
for objectID in updatedObjectIDs {
context?.object(with: objectID).willAccessValue(forKey: nil)
}
}
context?.mergeChangesFromContextDidSaveNotification(note)
context?.mergeChanges(fromContextDidSave: note)
}
}
)
@@ -94,15 +96,15 @@ internal extension NSManagedObjectContext {
}
@nonobjc
internal static func mainContextForRootContext(rootContext: NSManagedObjectContext) -> NSManagedObjectContext {
internal static func mainContextForRootContext(_ rootContext: NSManagedObjectContext) -> NSManagedObjectContext {
let context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
context.parentContext = rootContext
let context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
context.parent = rootContext
context.mergePolicy = NSRollbackMergePolicy
context.undoManager = nil
context.setupForCoreStoreWithContextName("com.corestore.maincontext")
context.observerForDidSaveNotification = NotificationObserver(
notificationName: NSManagedObjectContextDidSaveNotification,
notificationName: NSNotification.Name.NSManagedObjectContextDidSave,
object: rootContext,
closure: { [weak context] (note) -> Void in
@@ -113,21 +115,22 @@ internal extension NSManagedObjectContext {
}
let mergeChanges = { () -> Void in
let updatedObjects = (note.userInfo?[NSUpdatedObjectsKey] as? Set<NSManagedObject>) ?? []
for object in updatedObjects {
if let updatedObjects = (note.userInfo?[NSUpdatedObjectsKey] as? Set<NSManagedObject>) {
context.objectWithID(object.objectID).willAccessValueForKey(nil)
for object in updatedObjects {
context.object(with: object.objectID).willAccessValue(forKey: nil)
}
}
context.mergeChangesFromContextDidSaveNotification(note)
context.mergeChanges(fromContextDidSave: note)
}
if rootContext.isSavingSynchronously == true {
context.performBlockAndWait(mergeChanges)
context.performAndWait(mergeChanges)
}
else {
context.performBlock(mergeChanges)
context.perform(mergeChanges)
}
}
)

View File

@@ -25,9 +25,6 @@
import Foundation
import CoreData
#if USE_FRAMEWORKS
import GCDKit
#endif
// MARK: - NSManagedObjectContext
@@ -70,13 +67,55 @@ internal extension NSManagedObjectContext {
set {
cs_setAssociatedWeakObject(
newValue.flatMap { NSNumber(bool: $0) },
newValue.flatMap { NSNumber(value: $0) },
forKey: &PropertyKeys.isSavingSynchronously,
inObject: self
)
}
}
@nonobjc
internal var isTransactionContext: Bool {
get {
let value: NSNumber? = cs_getAssociatedObjectForKey(
&PropertyKeys.isTransactionContext,
inObject: self
)
return value?.boolValue == true
}
set {
cs_setAssociatedCopiedObject(
NSNumber(value: newValue),
forKey: &PropertyKeys.isTransactionContext,
inObject: self
)
}
}
@nonobjc
internal var isDataStackContext: Bool {
get {
let value: NSNumber? = cs_getAssociatedObjectForKey(
&PropertyKeys.isDataStackContext,
inObject: self
)
return value?.boolValue == true
}
set {
cs_setAssociatedCopiedObject(
NSNumber(value: newValue),
forKey: &PropertyKeys.isDataStackContext,
inObject: self
)
}
}
@nonobjc
internal func isRunningInAllowedQueue() -> Bool {
@@ -88,10 +127,10 @@ internal extension NSManagedObjectContext {
}
@nonobjc
internal func temporaryContextInTransactionWithConcurrencyType(concurrencyType: NSManagedObjectContextConcurrencyType) -> NSManagedObjectContext {
internal func temporaryContextInTransactionWithConcurrencyType(_ concurrencyType: NSManagedObjectContextConcurrencyType) -> NSManagedObjectContext {
let context = NSManagedObjectContext(concurrencyType: concurrencyType)
context.parentContext = self
context.parent = self
context.parentStack = self.parentStack
context.setupForCoreStoreWithContextName("com.corestore.temporarycontext")
context.shouldCascadeSavesToParent = (self.parentStack?.rootSavingContext == self)
@@ -105,7 +144,7 @@ internal extension NSManagedObjectContext {
var result = SaveResult(hasChanges: false)
self.performBlockAndWait {
self.performAndWait {
guard self.hasChanges else {
@@ -123,20 +162,20 @@ internal extension NSManagedObjectContext {
let saveError = CoreStoreError(error)
CoreStore.log(
saveError,
"Failed to save \(cs_typeName(NSManagedObjectContext))."
"Failed to save \(cs_typeName(NSManagedObjectContext.self))."
)
result = SaveResult(saveError)
return
}
if let parentContext = self.parentContext where self.shouldCascadeSavesToParent {
if let parentContext = self.parent, self.shouldCascadeSavesToParent {
switch parentContext.saveSynchronously(waitForMerge: waitForMerge) {
case .Success:
case .success:
result = SaveResult(hasChanges: true)
case .Failure(let error):
case .failure(let error):
result = SaveResult(error)
}
}
@@ -150,15 +189,15 @@ internal extension NSManagedObjectContext {
}
@nonobjc
internal func saveAsynchronouslyWithCompletion(completion: ((result: SaveResult) -> Void) = { _ in }) {
internal func saveAsynchronouslyWithCompletion(_ completion: @escaping ((_ result: SaveResult) -> Void) = { _ in }) {
self.performBlock {
self.perform {
guard self.hasChanges else {
GCDQueue.Main.async {
DispatchQueue.main.async {
completion(result: SaveResult(hasChanges: false))
completion(SaveResult(hasChanges: false))
}
return
}
@@ -174,24 +213,24 @@ internal extension NSManagedObjectContext {
let saveError = CoreStoreError(error)
CoreStore.log(
saveError,
"Failed to save \(cs_typeName(NSManagedObjectContext))."
"Failed to save \(cs_typeName(NSManagedObjectContext.self))."
)
GCDQueue.Main.async {
DispatchQueue.main.async {
completion(result: SaveResult(saveError))
completion(SaveResult(saveError))
}
return
}
if let parentContext = self.parentContext where self.shouldCascadeSavesToParent {
if self.shouldCascadeSavesToParent, let parentContext = self.parent {
parentContext.saveAsynchronouslyWithCompletion(completion)
}
else {
GCDQueue.Main.async {
DispatchQueue.main.async {
completion(result: SaveResult(hasChanges: true))
completion(SaveResult(hasChanges: true))
}
}
}
@@ -206,7 +245,7 @@ internal extension NSManagedObjectContext {
}
else {
self.registeredObjects.forEach { self.refreshObject($0, mergeChanges: true) }
self.registeredObjects.forEach { self.refresh($0, mergeChanges: true) }
}
}
@@ -217,5 +256,7 @@ internal extension NSManagedObjectContext {
static var parentTransaction: Void?
static var isSavingSynchronously: Void?
static var isTransactionContext: Void?
static var isDataStackContext: Void?
}
}

View File

@@ -34,32 +34,34 @@ internal extension NSManagedObjectModel {
// MARK: Internal
@nonobjc
internal static func fromBundle(bundle: NSBundle, modelName: String, modelVersionHints: Set<String> = []) -> NSManagedObjectModel {
internal static func fromBundle(_ bundle: Bundle, modelName: String, modelVersionHints: Set<String> = []) -> NSManagedObjectModel {
guard let modelFilePath = bundle.pathForResource(modelName, ofType: "momd") else {
guard let modelFilePath = bundle.path(forResource: modelName, ofType: "momd") else {
// For users migrating from very old Xcode versions: Old xcdatamodel files are not contained inside xcdatamodeld (with a "d"), and will thus fail this check. If that was the case, create a new xcdatamodeld file and copy all contents into the new model.
CoreStore.abort("Could not find \"\(modelName).momd\" from the bundle. \(bundle)")
}
let modelFileURL = NSURL(fileURLWithPath: modelFilePath)
let versionInfoPlistURL = modelFileURL.URLByAppendingPathComponent("VersionInfo.plist", isDirectory: false)!
let modelFileURL = URL(fileURLWithPath: modelFilePath)
let versionInfoPlistURL = modelFileURL.appendingPathComponent("VersionInfo.plist", isDirectory: false)
guard let versionInfo = NSDictionary(contentsOfURL: versionInfoPlistURL),
guard let versionInfo = NSDictionary(contentsOf: versionInfoPlistURL),
let versionHashes = versionInfo["NSManagedObjectModel_VersionHashes"] as? [String: AnyObject] else {
CoreStore.abort("Could not load \(cs_typeName(NSManagedObjectModel)) metadata from path \"\(versionInfoPlistURL)\".")
CoreStore.abort("Could not load \(cs_typeName(NSManagedObjectModel.self)) metadata from path \"\(versionInfoPlistURL)\".")
}
let modelVersions = Set(versionHashes.keys)
let currentModelVersion: String
if let plistModelVersion = versionInfo["NSManagedObjectModel_CurrentVersionName"] as? String where modelVersionHints.isEmpty || modelVersionHints.contains(plistModelVersion) {
if let plistModelVersion = versionInfo["NSManagedObjectModel_CurrentVersionName"] as? String,
modelVersionHints.isEmpty || modelVersionHints.contains(plistModelVersion) {
currentModelVersion = plistModelVersion
}
else if let resolvedVersion = modelVersions.intersect(modelVersionHints).first {
else if let resolvedVersion = modelVersions.intersection(modelVersionHints).first {
CoreStore.log(
.Warning,
.warning,
message: "The MigrationChain leaf versions do not include the model file's current version. Resolving to version \"\(resolvedVersion)\"."
)
currentModelVersion = resolvedVersion
@@ -69,7 +71,7 @@ internal extension NSManagedObjectModel {
if !modelVersionHints.isEmpty {
CoreStore.log(
.Warning,
.warning,
message: "The MigrationChain leaf versions do not include any of the model file's embedded versions. Resolving to version \"\(resolvedVersion)\"."
)
}
@@ -80,10 +82,10 @@ internal extension NSManagedObjectModel {
CoreStore.abort("No model files were found in URL \"\(modelFileURL)\".")
}
var modelVersionFileURL: NSURL?
var modelVersionFileURL: URL?
for modelVersion in modelVersions {
let fileURL = modelFileURL.URLByAppendingPathComponent("\(modelVersion).mom", isDirectory: false)!
let fileURL = modelFileURL.appendingPathComponent("\(modelVersion).mom", isDirectory: false)
if modelVersion == currentModelVersion {
@@ -92,13 +94,13 @@ internal extension NSManagedObjectModel {
}
precondition(
NSManagedObjectModel(contentsOfURL: fileURL) != nil,
NSManagedObjectModel(contentsOf: fileURL) != nil,
"Could not find the \"\(modelVersion).mom\" version file for the model at URL \"\(modelFileURL)\"."
)
}
if let modelVersionFileURL = modelVersionFileURL,
let rootModel = NSManagedObjectModel(contentsOfURL: modelVersionFileURL) {
let rootModel = NSManagedObjectModel(contentsOf: modelVersionFileURL) {
rootModel.modelVersionFileURL = modelVersionFileURL
rootModel.modelVersions = modelVersions
@@ -106,7 +108,7 @@ internal extension NSManagedObjectModel {
return rootModel
}
CoreStore.abort("Could not create an \(cs_typeName(NSManagedObjectModel)) from the model at URL \"\(modelFileURL)\".")
CoreStore.abort("Could not create an \(cs_typeName(NSManagedObjectModel.self)) from the model at URL \"\(modelFileURL)\".")
}
@nonobjc
@@ -152,7 +154,7 @@ internal extension NSManagedObjectModel {
}
@nonobjc
internal func entityNameForClass(entityClass: AnyClass) -> String {
internal func entityNameForClass(_ entityClass: AnyClass) -> String {
return self.entityNameMapping[NSStringFromClass(entityClass)]!
}
@@ -183,14 +185,14 @@ internal extension NSManagedObjectModel {
}
guard let modelFileURL = self.modelFileURL,
let modelVersions = self.modelVersions
where modelVersions.contains(modelVersion) else {
let modelVersions = self.modelVersions,
modelVersions.contains(modelVersion) else {
return nil
}
let versionModelFileURL = modelFileURL.URLByAppendingPathComponent("\(modelVersion).mom", isDirectory: false)
guard let model = NSManagedObjectModel(contentsOfURL: versionModelFileURL!) else {
let versionModelFileURL = modelFileURL.appendingPathComponent("\(modelVersion).mom", isDirectory: false)
guard let model = NSManagedObjectModel(contentsOf: versionModelFileURL) else {
return nil
}
@@ -202,15 +204,15 @@ internal extension NSManagedObjectModel {
}
@nonobjc
internal subscript(metadata: [String: AnyObject]) -> NSManagedObjectModel? {
internal subscript(metadata: [String: Any]) -> NSManagedObjectModel? {
guard let modelHashes = metadata[NSStoreModelVersionHashesKey] as? [String : NSData] else {
guard let modelHashes = metadata[NSStoreModelVersionHashesKey] as? [String : Data] else {
return nil
}
for modelVersion in self.modelVersions ?? [] {
if let versionModel = self[modelVersion] where modelHashes == versionModel.entityVersionHashesByName {
if let versionModel = self[modelVersion], modelHashes == versionModel.entityVersionHashesByName {
return versionModel
}
@@ -222,16 +224,16 @@ internal extension NSManagedObjectModel {
// MARK: Private
@nonobjc
private var modelFileURL: NSURL? {
private var modelFileURL: URL? {
get {
return self.modelVersionFileURL?.URLByDeletingLastPathComponent
return self.modelVersionFileURL?.deletingLastPathComponent()
}
}
@nonobjc
private var modelVersionFileURL: NSURL? {
private var modelVersionFileURL: URL? {
get {
@@ -239,12 +241,12 @@ internal extension NSManagedObjectModel {
&PropertyKeys.modelVersionFileURL,
inObject: self
)
return value
return value as URL?
}
set {
cs_setAssociatedCopiedObject(
newValue,
newValue as NSURL?,
forKey: &PropertyKeys.modelVersionFileURL,
inObject: self
)
@@ -270,7 +272,7 @@ internal extension NSManagedObjectModel {
}
let className = $0.managedObjectClassName
mapping[className] = entityName
mapping[className!] = entityName
}
cs_setAssociatedCopiedObject(
mapping as NSDictionary,

View File

@@ -66,15 +66,15 @@ internal extension NSPersistentStore {
// MARK: - StorageObject
private class StorageObject: NSObject {
fileprivate class StorageObject: NSObject {
// MARK: Private
@nonobjc
private let storageInterface: StorageInterface?
fileprivate let storageInterface: StorageInterface?
@nonobjc
private init(_ storage: StorageInterface?) {
fileprivate init(_ storage: StorageInterface?) {
self.storageInterface = storage
}

View File

@@ -26,134 +26,53 @@
import Foundation
import CoreData
#if USE_FRAMEWORKS
import GCDKit
#endif
// MARK: - NSPersistentStoreCoordinator
internal extension NSPersistentStoreCoordinator {
@nonobjc
internal func performAsynchronously(closure: () -> Void) {
internal func performAsynchronously(_ closure: @escaping () -> Void) {
#if USE_FRAMEWORKS
self.performBlock(closure)
#else
if #available(iOS 8.0, *) {
self.performBlock(closure)
}
else {
self.lock()
GCDQueue.Default.async {
closure()
self.unlock()
}
}
#endif
self.perform(closure)
}
@nonobjc
internal func performSynchronously<T>(closure: () -> T) -> T {
internal func performSynchronously<T>(_ closure: @escaping () -> T) -> T {
var result: T?
#if USE_FRAMEWORKS
self.performAndWait {
self.performBlockAndWait {
result = closure()
}
#else
if #available(iOS 8.0, *) {
self.performBlockAndWait {
result = closure()
}
}
else {
self.lock()
cs_autoreleasepool {
result = closure()
}
self.unlock()
}
#endif
result = closure()
}
return result!
}
@nonobjc
internal func performSynchronously<T>(closure: () throws -> T) throws -> T {
internal func performSynchronously<T>(_ closure: @escaping () throws -> T) throws -> T {
var closureError: ErrorType?
var closureError: Error?
var result: T?
#if USE_FRAMEWORKS
self.performAndWait {
self.performBlockAndWait {
do {
do {
result = try closure()
}
catch {
closureError = error
}
result = try closure()
}
#else
if #available(iOS 8.0, *) {
catch {
self.performBlockAndWait {
do {
result = try closure()
}
catch {
closureError = error
}
}
closureError = error
}
else {
self.lock()
cs_autoreleasepool {
do {
result = try closure()
}
catch {
closureError = error
}
}
self.unlock()
}
#endif
}
if let closureError = closureError {
throw closureError
}
return result!
}
@nonobjc
internal func addPersistentStoreSynchronously(storeType: String, configuration: String?, URL storeURL: NSURL?, options: [NSObject : AnyObject]?) throws -> NSPersistentStore {
internal func addPersistentStoreSynchronously(_ storeType: String, configuration: String?, URL storeURL: URL?, options: [NSObject : AnyObject]?) throws -> NSPersistentStore {
var store: NSPersistentStore?
var storeError: NSError?
@@ -161,10 +80,10 @@ internal extension NSPersistentStoreCoordinator {
do {
store = try self.addPersistentStoreWithType(
storeType,
configuration: configuration,
URL: storeURL,
store = try self.addPersistentStore(
ofType: storeType,
configurationName: configuration,
at: storeURL,
options: options
)
}
@@ -173,12 +92,10 @@ internal extension NSPersistentStoreCoordinator {
storeError = error as NSError
}
}
if let store = store {
return store
}
throw CoreStoreError(storeError)
}
}
}

View File

@@ -34,18 +34,18 @@ internal final class NotificationObserver {
let observer: NSObjectProtocol
init(notificationName: String, object: AnyObject?, queue: NSOperationQueue? = nil, closure: (note: NSNotification) -> Void) {
init(notificationName: Notification.Name, object: Any?, queue: OperationQueue? = nil, closure: @escaping (_ note: Notification) -> Void) {
self.observer = NSNotificationCenter.defaultCenter().addObserverForName(
notificationName,
self.observer = NotificationCenter.default.addObserver(
forName: notificationName,
object: object,
queue: queue,
usingBlock: closure
using: closure
)
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self.observer)
NotificationCenter.default.removeObserver(self.observer)
}
}