updated error handling for DataStack methods, updated migration demo app

This commit is contained in:
John Rommel Estropia
2015-07-12 19:20:38 +09:00
parent 8cfe8e2500
commit a64bcc474e
28 changed files with 773 additions and 393 deletions

View File

@@ -50,9 +50,8 @@ public extension NSProgress {
get {
let object: AnyObject? = getAssociatedObjectForKey(&PropertyKeys.progressObserver, inObject: self)
if let observer = object as? ProgressObserver {
let object: ProgressObserver? = getAssociatedObjectForKey(&PropertyKeys.progressObserver, inObject: self)
if let observer = object {
return observer
}
@@ -72,41 +71,58 @@ public extension NSProgress {
@objc private final class ProgressObserver: NSObject {
private weak var progress: NSProgress?
private var progressHandler: ((progress: NSProgress) -> Void)?
private unowned let progress: NSProgress
private var progressHandler: ((progress: NSProgress) -> Void)? {
didSet {
let progressHandler = self.progressHandler
if (progressHandler == nil) == (oldValue == nil) {
return
}
if let _ = progressHandler {
self.progress.addObserver(
self,
forKeyPath: "fractionCompleted",
options: [.Initial, .New],
context: nil
)
}
else {
self.progress.removeObserver(self, forKeyPath: "fractionCompleted")
}
}
}
private init(_ progress: NSProgress) {
self.progress = progress
super.init()
progress.addObserver(
self,
forKeyPath: "fractionCompleted",
options: .New,
context: nil
)
}
deinit {
progress?.removeObserver(self, forKeyPath: "fractionCompleted")
if let _ = self.progressHandler {
self.progressHandler = nil
self.progress.removeObserver(self, forKeyPath: "fractionCompleted")
}
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
guard let progress = self.progress where object as? NSProgress == progress && keyPath == "fractionCompleted" else {
guard let progress = object as? NSProgress where progress == self.progress && keyPath == "fractionCompleted" else {
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
return
}
GCDQueue.Main.async { [weak self] () -> Void in
if let strongSelf = self, let progress = strongSelf.progress {
strongSelf.progressHandler?(progress: progress)
}
self?.progressHandler?(progress: progress)
}
}
}

View File

@@ -52,7 +52,6 @@ internal extension NSManagedObjectModel {
let modelVersions = Set(versionHashes.keys)
let currentModelVersion: String
if let modelVersion = modelVersion {
currentModelVersion = modelVersion

View File

@@ -0,0 +1,144 @@
//
// CoreStore+Migration.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: - CoreStore
public extension CoreStore {
/**
Asynchronously adds to the `defaultStack` an SQLite store from the given SQLite file name. Note that using `addSQLiteStore(...)` instead of `addSQLiteStoreAndWait(...)` implies that the migrations are allowed and expected (thus the asynchronous `completion`.)
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support" directory. A new SQLite file will be created if it does not exist. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.allBundles()`.
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `PersistentStoreResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a `.Failure` result if an error occurs asynchronously.
- returns: an `NSProgress` instance if a migration has started, or `nil` is no migrations are required
*/
public static func addSQLiteStore(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle]? = nil, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
return try self.defaultStack.addSQLiteStore(
fileName: fileName,
configuration: configuration,
mappingModelBundles: mappingModelBundles,
completion: completion
)
}
/**
Asynchronously adds to the `defaultStack` an SQLite store from the given SQLite file URL. Note that using `addSQLiteStore(...)` instead of `addSQLiteStoreAndWait(...)` implies that the migrations are allowed and expected (thus the asynchronous `completion`.)
- parameter fileURL: the local file URL for the SQLite persistent store. A new SQLite file will be created if it does not exist. If not specified, defaults to a file URL pointing to a "<Application name>.sqlite" file in the "Application Support" directory. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.allBundles()`.
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `PersistentStoreResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a `.Failure` result if an error occurs asynchronously.
- returns: an `NSProgress` instance if a migration has started, or `nil` is no migrations are required
*/
public static func addSQLiteStore(fileURL fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, mappingModelBundles: [NSBundle]? = NSBundle.allBundles(), completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
return try self.defaultStack.addSQLiteStore(
fileURL: fileURL,
configuration: configuration,
mappingModelBundles: mappingModelBundles,
completion: completion
)
}
/**
Using the `defaultStack`, migrates an SQLite store with the specified filename to the `DataStack`'s managed object model version WITHOUT adding the migrated store to the data stack.
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support" directory.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil` which indicates the "Default" configuration.
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.mainBundle()`.
- parameter sourceBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.mainBundle()`.
- returns: an `NSProgress` instance if a migration has started, or `nil` is no migrations are required
*/
public static func upgradeSQLiteStoreIfNeeded(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle]? = nil, completion: (MigrationResult) -> Void) throws -> NSProgress? {
return try self.defaultStack.upgradeSQLiteStoreIfNeeded(
fileName: fileName,
configuration: configuration,
mappingModelBundles: mappingModelBundles,
completion: completion
)
}
/**
Using the `defaultStack`, migrates an SQLite store at the specified file URL and configuration name to the `DataStack`'s managed object model version. This method does NOT add the migrated store to the data stack.
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support" directory.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil` which indicates the "Default" configuration.
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.mainBundle()`.
- parameter sourceBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.mainBundle()`.
- returns: an `NSProgress` instance if a migration has started, or `nil` is no migrations are required
*/
public static func upgradeSQLiteStoreIfNeeded(fileURL fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, mappingModelBundles: [NSBundle]? = nil, completion: (MigrationResult) -> Void) throws -> NSProgress? {
return try self.defaultStack.upgradeSQLiteStoreIfNeeded(
fileURL: fileURL,
configuration: configuration,
mappingModelBundles: mappingModelBundles,
completion: completion
)
}
/**
Using the `defaultStack`, checks for the required migrations needed for the store with the specified filename and configuration to be migrated to the `DataStack`'s managed object model version. This method throws an error if the store does not exist, if inspection of the store failed, or no mapping model was found/inferred.
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support" directory.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil` which indicates the "Default" configuration.
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.allBundles()`.
:return: an array of `MigrationType`s indicating the chain of migrations required for the store; or `nil` if either inspection of the store failed, or no mapping model was found/inferred. `MigrationType` acts as a `Bool` and evaluates to `false` if no migration is required, and `true` if either a lightweight or custom migration is needed.
*/
public static func requiredMigrationsForSQLiteStore(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles() as [NSBundle]) throws -> [MigrationType] {
return try self.defaultStack.requiredMigrationsForSQLiteStore(
fileName: fileName,
configuration: configuration,
mappingModelBundles: mappingModelBundles
)
}
/**
Using the `defaultStack`, checks if the store at the specified file URL and configuration needs to be migrated to the `DataStack`'s managed object model version.
- parameter fileURL: the local file URL for the SQLite persistent store.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil` which indicates the "Default" configuration.
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.allBundles()`.
:return: a `MigrationType` indicating the type of migration required for the store; or `nil` if either inspection of the store failed, or no mapping model was found/inferred. `MigrationType` acts as a `Bool` and evaluates to `false` if no migration is required, and `true` if either a lightweight or custom migration is needed.
*/
public static func requiredMigrationsForSQLiteStore(fileURL fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles() as [NSBundle]) throws -> [MigrationType] {
return try self.defaultStack.requiredMigrationsForSQLiteStore(
fileURL: fileURL,
configuration: configuration,
mappingModelBundles: mappingModelBundles
)
}
}

View File

@@ -38,7 +38,7 @@ public extension DataStack {
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support" directory. A new SQLite file will be created if it does not exist. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.allBundles()`.
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `PersistentStoreResult` argument indicates the result. If an error is thrown, this closure will not be executed.
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `PersistentStoreResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a `.Failure` result if an error occurs asynchronously.
- returns: an `NSProgress` instance if a migration has started, or `nil` is no migrations are required
*/
public func addSQLiteStore(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle]? = nil, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
@@ -60,7 +60,7 @@ public extension DataStack {
- parameter fileURL: the local file URL for the SQLite persistent store. A new SQLite file will be created if it does not exist. If not specified, defaults to a file URL pointing to a "<Application name>.sqlite" file in the "Application Support" directory. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.allBundles()`.
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `PersistentStoreResult` argument indicates the result.
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `PersistentStoreResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a `.Failure` result if an error occurs asynchronously.
- returns: an `NSProgress` instance if a migration has started, or `nil` is no migrations are required
*/
public func addSQLiteStore(fileURL fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, mappingModelBundles: [NSBundle]? = NSBundle.allBundles(), completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
@@ -124,28 +124,38 @@ public extension DataStack {
return
}
let persistentStoreResult = self.addSQLiteStoreAndWait(
fileURL: fileURL,
configuration: configuration,
automigrating: false,
resetStoreOnMigrationFailure: false
)
completion(persistentStoreResult)
do {
let store = try self.addSQLiteStoreAndWait(
fileURL: fileURL,
configuration: configuration,
automigrating: false,
resetStoreOnMigrationFailure: false
)
completion(PersistentStoreResult(store))
}
catch {
completion(PersistentStoreResult(error as NSError))
}
}
)
}
catch let error as NSError
where error.code == NSFileReadNoSuchFileError && error.domain == NSCocoaErrorDomain {
let persistentStoreResult = self.addSQLiteStoreAndWait(
let store = try self.addSQLiteStoreAndWait(
fileURL: fileURL,
configuration: configuration,
automigrating: false,
resetStoreOnMigrationFailure: false
)
completion(persistentStoreResult)
GCDQueue.Main.async {
completion(PersistentStoreResult(store))
}
return nil
}
catch {
@@ -312,12 +322,16 @@ public extension DataStack {
var operations = [NSOperation]()
var cancelled = false
let progress = NSProgress(totalUnitCount: numberOfMigrations)
let progress = NSProgress(parent: nil, userInfo: nil)
progress.totalUnitCount = numberOfMigrations
// todo nsprogress crashing sometimes
for (sourceModel, destinationModel, mappingModel, _) in migrationSteps {
progress.becomeCurrentWithPendingUnitCount(1)
let childProgress = NSProgress(totalUnitCount: 100)
let childProgress = NSProgress(parent: progress, userInfo: nil)
childProgress.totalUnitCount = 100
operations.append(
NSBlockOperation { [weak self] in
@@ -338,7 +352,6 @@ public extension DataStack {
mappingModel: mappingModel,
progress: childProgress
)
childProgress.setProgressHandler(nil)
}
catch {
@@ -365,9 +378,8 @@ public extension DataStack {
GCDQueue.Main.async {
progress.setProgressHandler(nil)
completion(migrationResult ?? MigrationResult(migrationTypes))
withExtendedLifetime(progress) { (_: NSProgress) -> Void in }
return
}
}

View File

@@ -35,12 +35,12 @@ public extension CoreStore {
/**
Adds an in-memory store to the `defaultStack`.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to nil.
- returns: a `PersistentStoreResult` indicating success or failure.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`.
- returns: the `NSPersistentStore` added to the stack.
*/
public static func addInMemoryStore(configuration: String? = nil) -> PersistentStoreResult {
public static func addInMemoryStore(configuration configuration: String? = nil) throws -> NSPersistentStore {
return self.defaultStack.addInMemoryStore(configuration: configuration)
return try self.defaultStack.addInMemoryStore(configuration: configuration)
}
/**
@@ -50,11 +50,11 @@ public extension CoreStore {
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to nil.
- parameter automigrating: Set to true to configure Core Data auto-migration, or false to disable. If not specified, defaults to true.
- parameter resetStoreOnMigrationFailure: Set to true to delete the store on migration failure; or set to false to throw exceptions on failure instead. Typically should only be set to true when debugging, or if the persistent store can be recreated easily. If not specified, defaults to false
- returns: a `PersistentStoreResult` indicating success or failure.
- returns: the `NSPersistentStore` added to the stack.
*/
public static func addSQLiteStoreAndWait(fileName fileName: String, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult {
public static func addSQLiteStoreAndWait(fileName fileName: String, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) throws -> NSPersistentStore {
return self.defaultStack.addSQLiteStoreAndWait(
return try self.defaultStack.addSQLiteStoreAndWait(
fileName: fileName,
configuration: configuration,
automigrating: automigrating,
@@ -69,16 +69,15 @@ public extension CoreStore {
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to nil.
- parameter automigrating: Set to true to configure Core Data auto-migration, or false to disable. If not specified, defaults to true.
- parameter resetStoreOnMigrationFailure: Set to true to delete the store on migration failure; or set to false to throw exceptions on failure instead. Typically should only be set to true when debugging, or if the persistent store can be recreated easily. If not specified, defaults to false.
- returns: a `PersistentStoreResult` indicating success or failure.
- returns: the `NSPersistentStore` added to the stack.
*/
public static func addSQLiteStoreAndWait(fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult {
public static func addSQLiteStoreAndWait(fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) throws -> NSPersistentStore {
return self.defaultStack.addSQLiteStoreAndWait(
return try self.defaultStack.addSQLiteStoreAndWait(
fileURL: fileURL,
configuration: configuration,
automigrating: automigrating,
resetStoreOnMigrationFailure: resetStoreOnMigrationFailure
)
}
}

View File

@@ -67,7 +67,6 @@ public final class DataStack {
self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator)
self.mainContext = NSManagedObjectContext.mainContextForRootContext(self.rootSavingContext)
self.bundle = bundle
self.model = model
self.migrationChain = migrationChain
@@ -75,7 +74,7 @@ public final class DataStack {
}
/**
Returns the `DataStack`'s model version. The version string is the same as the name of the .xcdatamodeld file.
Returns the `DataStack`'s model version. The version string is the same as the name of the version-specific .xcdatamodeld file.
*/
public var modelVersion: String {
@@ -85,10 +84,10 @@ public final class DataStack {
/**
Adds an in-memory store to the stack.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to nil.
- returns: a `PersistentStoreResult` indicating success or failure.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`.
- returns: the `NSPersistentStore` added to the stack.
*/
public func addInMemoryStore(configuration configuration: String? = nil) -> PersistentStoreResult {
public func addInMemoryStore(configuration configuration: String? = nil) throws -> NSPersistentStore {
let coordinator = self.coordinator;
@@ -114,25 +113,15 @@ public final class DataStack {
if let store = store {
self.updateMetadataForPersistentStore(store)
return PersistentStoreResult(store)
return store
}
if let error = storeError {
CoreStore.handleError(
error,
"Failed to add in-memory \(typeName(NSPersistentStore))."
)
return PersistentStoreResult(error)
}
else {
CoreStore.handleError(
NSError(coreStoreErrorCode: .UnknownError),
"Failed to add in-memory \(typeName(NSPersistentStore))."
)
return PersistentStoreResult(.UnknownError)
}
let error = storeError ?? NSError(coreStoreErrorCode: .UnknownError)
CoreStore.handleError(
error,
"Failed to add in-memory \(typeName(NSPersistentStore)) to the stack."
)
throw error
}
/**
@@ -142,11 +131,11 @@ public final class DataStack {
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter automigrating: Set to true to configure Core Data auto-migration, or false to disable. If not specified, defaults to true.
- parameter resetStoreOnMigrationFailure: Set to true to delete the store on migration failure; or set to false to throw exceptions on failure instead. Typically should only be set to true when debugging, or if the persistent store can be recreated easily. If not specified, defaults to false
- returns: a `PersistentStoreResult` indicating success or failure.
- returns: the `NSPersistentStore` added to the stack.
*/
public func addSQLiteStoreAndWait(fileName fileName: String, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult {
public func addSQLiteStoreAndWait(fileName fileName: String, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) throws -> NSPersistentStore {
return self.addSQLiteStoreAndWait(
return try self.addSQLiteStoreAndWait(
fileURL: applicationSupportDirectory.URLByAppendingPathComponent(
fileName,
isDirectory: false
@@ -164,9 +153,9 @@ public final class DataStack {
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter automigrating: Set to true to configure Core Data auto-migration, or false to disable. If not specified, defaults to true.
- parameter resetStoreOnMigrationFailure: Set to true to delete the store on migration failure; or set to false to throw exceptions on failure instead. Typically should only be set to true when debugging, or if the persistent store can be recreated easily. If not specified, defaults to false.
- returns: a `PersistentStoreResult` indicating success or failure.
- returns: the `NSPersistentStore` added to the stack.
*/
public func addSQLiteStoreAndWait(fileURL fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult {
public func addSQLiteStoreAndWait(fileURL fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) throws -> NSPersistentStore {
CoreStore.assert(
fileURL.fileURL,
@@ -182,15 +171,16 @@ public final class DataStack {
&& isExistingStoreAutomigrating == automigrating
&& store.configurationName == (configuration ?? Into.defaultConfigurationName) {
return PersistentStoreResult(store)
return store
}
let error = NSError(coreStoreErrorCode: .DifferentPersistentStoreExistsAtURL)
CoreStore.handleError(
NSError(coreStoreErrorCode: .DifferentPersistentStoreExistsAtURL),
error,
"Failed to add SQLite \(typeName(NSPersistentStore)) at \"\(fileURL)\" because a different \(typeName(NSPersistentStore)) at that URL already exists."
)
return PersistentStoreResult(.DifferentPersistentStoreExistsAtURL)
throw error
}
let fileManager = NSFileManager.defaultManager()
@@ -230,7 +220,7 @@ public final class DataStack {
if let store = store {
self.updateMetadataForPersistentStore(store)
return PersistentStoreResult(store)
return store
}
if let error = storeError
@@ -285,16 +275,16 @@ public final class DataStack {
if let store = store {
self.updateMetadataForPersistentStore(store)
return PersistentStoreResult(store)
return store
}
}
let error = storeError ?? NSError(coreStoreErrorCode: .UnknownError)
CoreStore.handleError(
storeError ?? NSError(coreStoreErrorCode: .UnknownError),
error,
"Failed to add SQLite \(typeName(NSPersistentStore)) at \"\(fileURL)\"."
)
return PersistentStoreResult(.UnknownError)
throw error
}
@@ -303,7 +293,6 @@ public final class DataStack {
internal let coordinator: NSPersistentStoreCoordinator
internal let rootSavingContext: NSManagedObjectContext
internal let mainContext: NSManagedObjectContext
internal let bundle: NSBundle
internal let model: NSManagedObjectModel
internal let migrationChain: MigrationChain
internal let childTransactionQueue: GCDQueue = .createSerial("com.corestore.datastack.childtransactionqueue")

View File

@@ -30,26 +30,28 @@ import CoreData
// MARK: - PersistentStoreResult
/**
The `PersistentStoreResult` indicates the result of initializing the persistent store.
The `PersistentStoreResult` indicates the result of an asynchronous initialization of a persistent store.
The `PersistentStoreResult` can be treated as a boolean:
let result = CoreStore.addSQLiteStoreAndWait()
if result {
// succeeded
}
else {
// failed
}
try! CoreStore.addSQLiteStore(completion: { (result: PersistentStoreResult) -> Void in
if result {
// succeeded
}
else {
// failed
}
})
or as an `enum`, where the resulting associated object can also be inspected:
let result = CoreStore.addSQLiteStoreAndWait()
switch result {
case .Success(let persistentStore):
// persistentStore is the related NSPersistentStore instance
case .Failure(let error):
// error is the NSError instance for the failure
}
try! CoreStore.addSQLiteStore(completion: { (result: PersistentStoreResult) -> Void in
switch result {
case .Success(let persistentStore):
// persistentStore is the related NSPersistentStore instance
case .Failure(let error):
// error is the NSError instance for the failure
}
})
```
*/
public enum PersistentStoreResult {