WIP: Xcode 8 beta 6

This commit is contained in:
John Estropia
2016-09-06 09:57:28 +09:00
parent e9be711d4c
commit 0ba63c6e72
78 changed files with 472 additions and 450 deletions

View File

@@ -25,9 +25,6 @@
import Foundation
import CoreData
#if USE_FRAMEWORKS
import GCDKit
#endif
// MARK: - CoreStore
@@ -50,7 +47,7 @@ public extension CoreStore {
- parameter storeType: the storage type
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
*/
public static func addStorage<T: StorageInterface where T: DefaultInitializableStore>(_ storeType: T.Type, completion: (SetupResult<T>) -> Void) {
public static func addStorage<T: StorageInterface>(_ storeType: T.Type, completion: (SetupResult<T>) -> Void) where T: DefaultInitializableStore {
self.defaultStack.addStorage(storeType.init(), completion: completion)
}
@@ -93,7 +90,7 @@ public extension CoreStore {
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
- returns: an `NSProgress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
*/
public static func addStorage<T: LocalStorage where T: DefaultInitializableStore>(_ storeType: T.Type, completion: (SetupResult<T>) -> Void) -> Progress? {
public static func addStorage<T: LocalStorage>(_ storeType: T.Type, completion: (SetupResult<T>) -> Void) -> Progress? where T: DefaultInitializableStore {
return self.defaultStack.addStorage(storeType.init(), completion: completion)
}

View File

@@ -25,9 +25,6 @@
import Foundation
import CoreData
#if USE_FRAMEWORKS
import GCDKit
#endif
// MARK: - DataStack
@@ -50,7 +47,7 @@ public extension DataStack {
- parameter storeType: the storage type
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
*/
public func addStorage<T: StorageInterface where T: DefaultInitializableStore>(_ storeType: T.Type, completion: (SetupResult<T>) -> Void) {
public func addStorage<T: StorageInterface>(_ storeType: T.Type, completion: (SetupResult<T>) -> Void) where T: DefaultInitializableStore {
self.addStorage(storeType.init(), completion: completion)
}
@@ -71,13 +68,13 @@ public extension DataStack {
- parameter storage: the storage
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
*/
public func addStorage<T: StorageInterface>(_ storage: T, completion: (SetupResult<T>) -> Void) {
public func addStorage<T: StorageInterface>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
self.coordinator.performAsynchronously {
if let _ = self.persistentStoreForStorage(storage) {
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(storage))
}
@@ -92,7 +89,7 @@ public extension DataStack {
finalStoreOptions: storage.storeOptions
)
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(storage))
}
@@ -104,7 +101,7 @@ public extension DataStack {
storeError,
"Failed to add \(cs_typeName(storage)) to the stack."
)
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(storeError))
}
@@ -129,9 +126,9 @@ public extension DataStack {
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
- returns: an `NSProgress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
*/
public func addStorage<T: LocalStorage where T: DefaultInitializableStore>(_ storeType: T.Type, completion: (SetupResult<T>) -> Void) -> Progress? {
public func addStorage<T: LocalStorage>(_ storeType: T.Type, completion: (SetupResult<T>) -> Void) -> Progress? where T: DefaultInitializableStore {
return self.addStorage(storeType.init(), completion: completion)
return self.addStorage(storeType.init() as! T.Type, completion: completion)
}
/**
@@ -151,7 +148,7 @@ public extension DataStack {
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
- returns: an `NSProgress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
*/
public func addStorage<T: LocalStorage>(_ storage: T, completion: (SetupResult<T>) -> Void) -> Progress? {
public func addStorage<T: LocalStorage>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) -> Progress? {
let fileURL = storage.fileURL
CoreStore.assert(
@@ -163,7 +160,7 @@ public extension DataStack {
if let _ = self.persistentStoreForStorage(storage) {
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(storage))
}
@@ -175,7 +172,7 @@ public extension DataStack {
if let existingStorage = persistentStore.storageInterface as? T,
storage.matchesPersistentStore(persistentStore) {
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(existingStorage))
}
@@ -187,7 +184,7 @@ public extension DataStack {
error,
"Failed to add \(cs_typeName(storage)) at \"\(fileURL)\" because a different \(cs_typeName(NSPersistentStore.self)) at that URL already exists."
)
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(error))
}
@@ -203,14 +200,14 @@ public extension DataStack {
)
let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
ofType: storage.dynamicType.storeType,
ofType: type(of: storage).storeType,
at: fileURL as URL,
options: storage.storeOptions
)
return self.upgradeStorageIfNeeded(
storage,
metadata: metadata,
metadata: metadata as [String : AnyObject],
completion: { (result) -> Void in
if case .failure(.internalError(let error)) = result {
@@ -222,7 +219,7 @@ public extension DataStack {
_ = try self.model[metadata].flatMap(storage.eraseStorageAndWait)
_ = try self.addStorageAndWait(storage)
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(storage))
}
@@ -258,14 +255,14 @@ public extension DataStack {
_ = try self.addStorageAndWait(storage)
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(storage))
}
}
catch {
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(error))
}
@@ -279,7 +276,7 @@ public extension DataStack {
storeError,
"Failed to load SQLite \(cs_typeName(NSPersistentStore.self)) metadata."
)
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(storeError))
}
@@ -315,14 +312,14 @@ public extension DataStack {
- parameter storage: the cloud storage
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `CloudStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
*/
public func addStorage<T: CloudStorage>(_ storage: T, completion: (SetupResult<T>) -> Void) {
public func addStorage<T: CloudStorage>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
let cacheFileURL = storage.cacheFileURL
self.coordinator.performSynchronously {
if let _ = self.persistentStoreForStorage(storage) {
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(storage))
}
@@ -334,7 +331,7 @@ public extension DataStack {
if let existingStorage = persistentStore.storageInterface as? T,
storage.matchesPersistentStore(persistentStore) {
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(existingStorage))
}
@@ -346,7 +343,7 @@ public extension DataStack {
error,
"Failed to add \(cs_typeName(storage)) at \"\(cacheFileURL)\" because a different \(cs_typeName(NSPersistentStore.self)) at that URL already exists."
)
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(error))
}
@@ -371,7 +368,7 @@ public extension DataStack {
finalURL: cacheFileURL,
finalStoreOptions: storeOptions
)
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(storage))
}
@@ -379,7 +376,7 @@ public extension DataStack {
catch let error as NSError where storage.cloudStorageOptions.contains(.recreateLocalStoreOnModelMismatch) && error.isCoreDataMigrationError {
let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
ofType: storage.dynamicType.storeType,
ofType: type(of: storage).storeType,
at: cacheFileURL,
options: storeOptions
)
@@ -398,14 +395,14 @@ public extension DataStack {
_ = try self.addStorageAndWait(storage)
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(storage))
}
}
catch {
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(error))
}
@@ -418,7 +415,7 @@ public extension DataStack {
storeError,
"Failed to load \(cs_typeName(NSPersistentStore.self)) metadata."
)
GCDQueue.main.async {
DispatchQueue.main.async {
completion(SetupResult(storeError))
}
@@ -447,13 +444,13 @@ public extension DataStack {
)
let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
ofType: storage.dynamicType.storeType,
ofType: type(of: storage).storeType,
at: fileURL as URL,
options: storage.storeOptions
)
return self.upgradeStorageIfNeeded(
storage,
metadata: metadata,
metadata: metadata as [String : AnyObject],
completion: completion
)
}
@@ -489,12 +486,12 @@ public extension DataStack {
do {
let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
ofType: storage.dynamicType.storeType,
ofType: type(of: storage).storeType,
at: fileURL as URL,
options: storage.storeOptions
)
guard let migrationSteps = self.computeMigrationFromStorage(storage, metadata: metadata) else {
guard let migrationSteps = self.computeMigrationFromStorage(storage, metadata: metadata as [String : AnyObject]) else {
let error = CoreStoreError.mappingModelNotFound(
localStoreURL: fileURL,
@@ -540,7 +537,7 @@ public extension DataStack {
// MARK: Private
private func upgradeStorageIfNeeded<T: LocalStorage>(_ storage: T, metadata: [String: AnyObject], completion: (MigrationResult) -> Void) -> Progress? {
private func upgradeStorageIfNeeded<T: LocalStorage>(_ storage: T, metadata: [String: AnyObject], completion: @escaping (MigrationResult) -> Void) -> Progress? {
guard let migrationSteps = self.computeMigrationFromStorage(storage, metadata: metadata) else {
@@ -554,7 +551,7 @@ public extension DataStack {
"Failed to find migration steps from \(cs_typeName(storage)) at URL \"\(storage.fileURL)\" to version model \"\(self.model)\"."
)
GCDQueue.main.async {
DispatchQueue.main.async {
completion(MigrationResult(error))
}
@@ -564,7 +561,7 @@ public extension DataStack {
let numberOfMigrations: Int64 = Int64(migrationSteps.count)
if numberOfMigrations == 0 {
GCDQueue.main.async {
DispatchQueue.main.async {
completion(MigrationResult([]))
return
@@ -578,7 +575,7 @@ public extension DataStack {
error,
"Failed to find migration mapping from the \(cs_typeName(storage)) at URL \"\(storage.fileURL)\" to version model \"\(self.modelVersion)\" without requiring progessive migrations."
)
GCDQueue.main.async {
DispatchQueue.main.async {
completion(MigrationResult(error))
}
@@ -627,7 +624,7 @@ public extension DataStack {
}
}
GCDQueue.main.async {
DispatchQueue.main.async {
_ = withExtendedLifetime(childProgress) { (_: Progress) -> Void in }
}
@@ -642,7 +639,7 @@ public extension DataStack {
operations.forEach { migrationOperation.addDependency($0) }
migrationOperation.addExecutionBlock { () -> Void in
GCDQueue.main.async {
DispatchQueue.main.async {
progress.setProgressHandler(nil)
completion(migrationResult ?? MigrationResult(migrationTypes))
@@ -752,7 +749,7 @@ public extension DataStack {
)
let temporaryFileURL = try! temporaryDirectoryURL.appendingPathComponent(
fileURL.lastPathComponent!,
fileURL.lastPathComponent,
isDirectory: false
)
@@ -766,11 +763,11 @@ public extension DataStack {
try migrationManager.migrateStore(
from: fileURL,
sourceType: storage.dynamicType.storeType,
sourceType: type(of: storage).storeType,
options: nil,
with: mappingModel,
toDestinationURL: temporaryFileURL,
destinationType: storage.dynamicType.storeType,
destinationType: type(of: storage).storeType,
destinationOptions: nil
)
}

View File

@@ -60,7 +60,7 @@ import CoreData
- a version appears twice as a key in a dictionary literal
- a loop is found in any of the paths
*/
public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, DictionaryLiteralConvertible, ArrayLiteralConvertible, Equatable {
public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLiteral, ExpressibleByDictionaryLiteral, ExpressibleByArrayLiteral, Equatable {
/**
Initializes the `MigrationChain` with empty values, which instructs the `DataStack` to use the .xcdatamodel's current version as the final version, and to disable progressive migrations.
@@ -87,7 +87,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
/**
Initializes the `MigrationChain` with a linear order of versions, which becomes the order of the `DataStack`'s progressive migrations.
*/
public init<T: Collection where T.Iterator.Element == String, T.SubSequence.Iterator.Element == String, T.Index: Comparable>(_ elements: T) {
public init<T: Collection>(_ elements: T) where T.Iterator.Element == String, T.SubSequence.Iterator.Element == String, T.Index: Comparable {
CoreStore.assert(Set(elements).count == Array(elements).count, "\(cs_typeName(MigrationChain.self))'s migration chain could not be created due to duplicate version strings.")
@@ -168,7 +168,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
}
// MARK: NilLiteralConvertible
// MARK: ExpressibleByNilLiteral
public init(nilLiteral: ()) {
@@ -176,7 +176,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
}
// MARK: StringLiteralConvertible
// MARK: ExpressibleByStringLiteral
public init(stringLiteral value: String) {
@@ -200,7 +200,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
}
// MARK: DictionaryLiteralConvertible
// MARK: ExpressibleByDictionaryLiteral
public init(dictionaryLiteral elements: (String, String)...) {
@@ -208,7 +208,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
}
// MARK: ArrayLiteralConvertible
// MARK: ExpressibleByArrayLiteral
public init(arrayLiteral elements: String...) {

View File

@@ -57,7 +57,7 @@ import Foundation
}
```
*/
public enum MigrationResult: Boolean, Hashable {
public enum MigrationResult: Hashable {
/**
`MigrationResult.success` indicates either the migration succeeded, or there were no migrations needed. The associated value is an array of `MigrationType`s reflecting the migration steps completed.
@@ -70,9 +70,10 @@ public enum MigrationResult: Boolean, Hashable {
case failure(CoreStoreError)
// MARK: BooleanType
public var boolValue: Bool {
/**
Returns `true` if the result indicates `.success`, `false` if the result is `.failure`.
*/
public var isSuccess: Bool {
switch self {
@@ -90,7 +91,7 @@ public enum MigrationResult: Boolean, Hashable {
case .success(let migrationTypes):
return self.boolValue.hashValue
^ migrationTypes.map { $0.hashValue }.reduce(0, combine: ^).hashValue
^ migrationTypes.map { $0.hashValue }.reduce(0, ^).hashValue
case .failure(let error):
return self.boolValue.hashValue ^ error.hashValue
@@ -110,7 +111,7 @@ public enum MigrationResult: Boolean, Hashable {
self = .failure(error)
}
internal init(_ error: ErrorProtocol) {
internal init(_ error: Error) {
self = .failure(CoreStoreError(error))
}

View File

@@ -31,7 +31,7 @@ import Foundation
/**
The `MigrationType` specifies the type of migration required for a store.
*/
public enum MigrationType: Boolean, Hashable {
public enum MigrationType: Hashable {
/**
Indicates that the persistent store matches the latest model version and no migration is needed
@@ -108,10 +108,10 @@ public enum MigrationType: Boolean, Hashable {
return false
}
// MARK: BooleanType
public var boolValue: Bool {
/**
Returns `true` if the `MigrationType` is either a lightweight or a heavyweight migration. Returns `false` if no migrations specified.
*/
public var hasMigration: Bool {
switch self {

View File

@@ -60,7 +60,7 @@ import CoreData
)
```
*/
public enum SetupResult<T: StorageInterface>: Boolean, Hashable {
public enum SetupResult<T: StorageInterface>: Hashable {
/**
`SetupResult.success` indicates that the storage setup succeeded. The associated object for this `enum` value is the related `StorageInterface` instance.
@@ -73,9 +73,10 @@ public enum SetupResult<T: StorageInterface>: Boolean, Hashable {
case failure(CoreStoreError)
// MARK: BooleanType
public var boolValue: Bool {
/**
Returns `true` if the result indicates `.success`, `false` if the result is `.failure`.
*/
public var isSuccess: Bool {
switch self {
@@ -112,7 +113,7 @@ public enum SetupResult<T: StorageInterface>: Boolean, Hashable {
self = .failure(error)
}
internal init(_ error: ErrorProtocol) {
internal init(_ error: Error) {
self = .failure(CoreStoreError(error))
}