From f18d29d9bcbb90c4b3fcd0f82df2f4663c6e121e Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Wed, 10 Jun 2015 10:37:16 +0900 Subject: [PATCH] created an asynchronous method for adding sqlite store to handle asynchronous migrations. note that this commit breaks previous usage of DataStack.addSQLiteStore(...), which is now renamed to addSQLiteStoreAndWait(...) --- CoreStore.xcodeproj/project.pbxproj | 12 + CoreStore/Migrating/DataStack+Migration.swift | 227 ++++++++++++++++++ CoreStore/Setting Up/CoreStore+Setup.swift | 8 +- CoreStore/Setting Up/DataStack.swift | 38 +-- .../Setting Up/PersistentStoreResult.swift | 4 +- .../CoreStoreDemo.xcodeproj/project.pbxproj | 46 +++- .../xcdebugger/Breakpoints_v2.xcbkptlist | 5 + .../CoreStoreDemo.xcdatamodel/contents | 12 - ...ObjectListObserverDemoViewController.swift | 2 +- .../CustomLoggerViewController.swift | 4 +- .../.xccurrentversion | 8 + .../MigrationDemo.xcdatamodel/contents | 7 + .../MigrationDemoV2.xcdatamodel/contents | 7 + .../Stack Setup Demo/FacebookAccount.swift | 15 -- .../Stack Setup Demo/FemaleAccount.swift | 15 ++ .../Stack Setup Demo/MaleAccount.swift | 15 ++ .../StackSetupDemoViewController.swift | 60 ++--- .../Stack Setup Demo/TwitterAccount.swift | 15 -- .../StackSetupDemo.xcdatamodel/contents | 23 ++ .../TransactionsDemoViewController.swift | 2 +- CoreStoreTests/CoreStoreTests.swift | 4 +- README.md | 10 +- 22 files changed, 419 insertions(+), 120 deletions(-) create mode 100644 CoreStore/Migrating/DataStack+Migration.swift create mode 100644 CoreStoreDemo/CoreStoreDemo.xcodeproj/xcuserdata/johnestropia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/.xccurrentversion create mode 100644 CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemo.xcdatamodel/contents create mode 100644 CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemoV2.xcdatamodel/contents delete mode 100644 CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/FacebookAccount.swift create mode 100644 CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/FemaleAccount.swift create mode 100644 CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/MaleAccount.swift delete mode 100644 CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/TwitterAccount.swift create mode 100644 CoreStoreDemo/CoreStoreDemo/StackSetupDemo.xcdatamodeld/StackSetupDemo.xcdatamodel/contents diff --git a/CoreStore.xcodeproj/project.pbxproj b/CoreStore.xcodeproj/project.pbxproj index c99c32d..c5a6a24 100644 --- a/CoreStore.xcodeproj/project.pbxproj +++ b/CoreStore.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 2F03A54D19C5C872005002A5 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F03A54C19C5C872005002A5 /* CoreData.framework */; }; 2F291E2719C6D3CF007AF63F /* CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F291E2619C6D3CF007AF63F /* CoreStore.swift */; }; B504D0D61B02362500B2BBB1 /* CoreStore+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */; }; + B56964D41B22FFAD0075EE4A /* DataStack+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */; }; B5D1E22C19FA9FBC003B2874 /* NSError+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22B19FA9FBC003B2874 /* NSError+CoreStore.swift */; }; B5D372841A39CD6900F583D9 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; }; B5D372861A39CDDB00F583D9 /* TestEntity1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D372851A39CDDB00F583D9 /* TestEntity1.swift */; }; @@ -99,6 +100,7 @@ 2F03A54C19C5C872005002A5 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 2F291E2619C6D3CF007AF63F /* CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CoreStore.swift; sourceTree = ""; }; B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Setup.swift"; sourceTree = ""; }; + B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DataStack+Migration.swift"; sourceTree = ""; }; B5D1E22B19FA9FBC003B2874 /* NSError+CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSError+CoreStore.swift"; sourceTree = ""; }; B5D372831A39CD6900F583D9 /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = ""; }; B5D372851A39CDDB00F583D9 /* TestEntity1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestEntity1.swift; sourceTree = ""; }; @@ -201,6 +203,7 @@ B5E84EE91AFF846E0064E85B /* Saving and Processing */, B5E84EFD1AFF847B0064E85B /* Fetching and Querying */, B5E84F191AFF84860064E85B /* Observing */, + B56964D11B22FF700075EE4A /* Migrating */, B5E84F261AFF84920064E85B /* Convenience Helpers */, B5E84F291AFF849C0064E85B /* Internal */, 2F03A53319C5C6DA005002A5 /* Supporting Files */, @@ -249,6 +252,14 @@ name = Frameworks; sourceTree = ""; }; + B56964D11B22FF700075EE4A /* Migrating */ = { + isa = PBXGroup; + children = ( + B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */, + ); + path = Migrating; + sourceTree = ""; + }; B5D806BB1A34715700A44484 /* Libraries */ = { isa = PBXGroup; children = ( @@ -531,6 +542,7 @@ B5E84EDF1AFF84500064E85B /* DataStack.swift in Sources */, B5E84F231AFF84860064E85B /* ManagedObjectListController.swift in Sources */, B5E84EF71AFF846E0064E85B /* DetachedDataTransaction.swift in Sources */, + B56964D41B22FFAD0075EE4A /* DataStack+Migration.swift in Sources */, B5E84EF51AFF846E0064E85B /* BaseDataTransaction.swift in Sources */, B5E84EFB1AFF846E0064E85B /* SaveResult.swift in Sources */, B5E84F0F1AFF847B0064E85B /* From.swift in Sources */, diff --git a/CoreStore/Migrating/DataStack+Migration.swift b/CoreStore/Migrating/DataStack+Migration.swift new file mode 100644 index 0000000..2aa8386 --- /dev/null +++ b/CoreStore/Migrating/DataStack+Migration.swift @@ -0,0 +1,227 @@ +// +// DataStack+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: - DataStack + +public extension DataStack { + + // MARK: Public + + /** + Initializes a `DataStack` from the specified model name and a version-specific model name. + + :param: rootModelName the name of the (.xcdatamodeld) model file + :param: versionModelName the name of the version-specific (.xcdatamodeld) model file + */ + public convenience init(rootModelName: String, versionModelName: String) { + + let modelVersionURL: NSURL! = NSBundle.mainBundle().URLForResource( + rootModelName.stringByAppendingPathExtension("momd")!.stringByAppendingPathComponent(versionModelName), + withExtension: "mom" + ) + CoreStore.assert(modelVersionURL != nil, "Could not find a \"mom\" resource from the main bundle.") + + let managedObjectModel: NSManagedObjectModel! = NSManagedObjectModel(contentsOfURL: modelVersionURL) + CoreStore.assert(managedObjectModel != nil, "Could not create an <\(NSManagedObjectModel.self)> from the resource at URL \"\(modelVersionURL)\".") + + self.init(managedObjectModel: managedObjectModel) + } + + /** + Checks if the store at the specified filename and configuration needs to be migrated to the `DataStack`'s managed object model version. + + :param: fileName the local filename for the SQLite persistent store in the "Application Support" directory. + :param: configuration an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. + */ + public func needsMigrationForSQLiteStore(fileName: String, configuration: String? = nil) -> Bool? { + + return needsMigrationForSQLiteStore( + fileURL: applicationSupportDirectory.URLByAppendingPathComponent( + fileName, + isDirectory: false + ), + configuration: configuration + ) + } + + /** + Checks if the store at the specified file URL and configuration needs to be migrated to the `DataStack`'s managed object model version. + + :param: fileName the local filename for the SQLite persistent store in the "Application Support" directory. + :param: configuration an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. + */ + public func needsMigrationForSQLiteStore(fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil) -> Bool? { + + var error: NSError? + let metadata = NSPersistentStoreCoordinator.metadataForPersistentStoreOfType( + NSSQLiteStoreType, + URL: fileURL, + error: &error + ) + if metadata == nil { + + CoreStore.handleError( + error ?? NSError(coreStoreErrorCode: .UnknownError), + "Failed to add SQLite <\(NSPersistentStore.self)> at \"\(fileURL)\".") + return nil + } + + return !self.coordinator.managedObjectModel.isConfiguration( + configuration, + compatibleWithStoreMetadata: metadata + ) + } + + /** + Asynchronously adds to the stack 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`.) + + :param: 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. + :param: 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. + :param: 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. + */ + public func addSQLiteStore(fileName: String, configuration: String? = nil, completion: (PersistentStoreResult) -> Void) { + + self.addSQLiteStore( + fileURL: applicationSupportDirectory.URLByAppendingPathComponent( + fileName, + isDirectory: false + ), + configuration: configuration, + completion: completion + ) + } + + /** + Asynchronously adds to the stack 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`.) + + :param: 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 ".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. + :param: 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. + :param: 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. + */ + public func addSQLiteStore(fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, completion: (PersistentStoreResult) -> Void) { + + var error: NSError? + let metadata = NSPersistentStoreCoordinator.metadataForPersistentStoreOfType( + NSSQLiteStoreType, + URL: fileURL, + error: &error + ) + if metadata == nil { + + CoreStore.handleError( + error ?? NSError(coreStoreErrorCode: .UnknownError), + "Failed to load SQLite <\(NSPersistentStore.self)> metadata at \"\(fileURL)\".") + + GCDQueue.Main.async { + + completion(PersistentStoreResult(.UnknownError)) + } + return + } + + let coordinator = self.coordinator; + if let store = coordinator.persistentStoreForURL(fileURL) { + + let isExistingStoreAutomigrating = ((store.options?[NSMigratePersistentStoresAutomaticallyOption] as? Bool) ?? false) + + if store.type == NSSQLiteStoreType + && isExistingStoreAutomigrating + && store.configurationName == (configuration ?? Into.defaultConfigurationName) { + + GCDQueue.Main.async { + + completion(PersistentStoreResult(store)) + } + return + } + + CoreStore.handleError( + NSError(coreStoreErrorCode: .DifferentPersistentStoreExistsAtURL), + "Failed to add SQLite <\(NSPersistentStore.self)> at \"\(fileURL)\" because a different <\(NSPersistentStore.self)> at that URL already exists.") + + GCDQueue.Main.async { + + completion(PersistentStoreResult(.DifferentPersistentStoreExistsAtURL)) + } + return + } + + let fileManager = NSFileManager.defaultManager() + var directoryError: NSError? + if !fileManager.createDirectoryAtURL( + fileURL.URLByDeletingLastPathComponent!, + withIntermediateDirectories: true, + attributes: nil, + error: &directoryError) { + + CoreStore.handleError( + directoryError ?? NSError(coreStoreErrorCode: .UnknownError), + "Failed to create directory for SQLite store at \"\(fileURL)\".") + GCDQueue.Main.async { + + completion(PersistentStoreResult(directoryError!)) + } + return + } + + coordinator.performBlock { + + var persistentStoreError: NSError? + let store = coordinator.addPersistentStoreWithType( + NSSQLiteStoreType, + configuration: configuration, + URL: fileURL, + options: [NSSQLitePragmasOption: ["WAL": "journal_mode"], + NSInferMappingModelAutomaticallyOption: true, + NSMigratePersistentStoresAutomaticallyOption: true], + error: &persistentStoreError) + + if let store = store { + + GCDQueue.Main.async { + + self.updateMetadataForPersistentStore(store) + completion(PersistentStoreResult(store)) + } + } + else { + + GCDQueue.Main.async { + + CoreStore.handleError( + persistentStoreError ?? NSError(coreStoreErrorCode: .UnknownError), + "Failed to add SQLite <\(NSPersistentStore.self)> at \"\(fileURL)\".") + + completion(PersistentStoreResult(.UnknownError)) + } + } + } + } +} diff --git a/CoreStore/Setting Up/CoreStore+Setup.swift b/CoreStore/Setting Up/CoreStore+Setup.swift index d6c5661..82db6dd 100644 --- a/CoreStore/Setting Up/CoreStore+Setup.swift +++ b/CoreStore/Setting Up/CoreStore+Setup.swift @@ -52,9 +52,9 @@ public extension CoreStore { :param: 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. */ - public static func addSQLiteStore(fileName: String, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult { + public static func addSQLiteStoreAndWait(fileName: String, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult { - return self.defaultStack.addSQLiteStore( + return self.defaultStack.addSQLiteStoreAndWait( fileName, configuration: configuration, automigrating: automigrating, @@ -71,9 +71,9 @@ public extension CoreStore { :param: 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. */ - public static func addSQLiteStore(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) -> PersistentStoreResult { - return self.defaultStack.addSQLiteStore( + return self.defaultStack.addSQLiteStoreAndWait( fileURL: fileURL, configuration: configuration, automigrating: automigrating, diff --git a/CoreStore/Setting Up/DataStack.swift b/CoreStore/Setting Up/DataStack.swift index b4f89fc..18f25b8 100644 --- a/CoreStore/Setting Up/DataStack.swift +++ b/CoreStore/Setting Up/DataStack.swift @@ -28,9 +28,9 @@ import CoreData import GCDKit -private let applicationSupportDirectory = NSFileManager.defaultManager().URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask).first as! NSURL +internal let applicationSupportDirectory = NSFileManager.defaultManager().URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask).first as! NSURL -private let applicationName = ((NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as? String) ?? "CoreData") +internal let applicationName = ((NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as? String) ?? "CoreData") internal let defaultSQLiteStoreURL = applicationSupportDirectory.URLByAppendingPathComponent(applicationName, isDirectory: false).URLByAppendingPathExtension("sqlite") @@ -152,9 +152,9 @@ public final class DataStack { :param: 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. */ - public func addSQLiteStore(fileName: String, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult { + public func addSQLiteStoreAndWait(fileName: String, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult { - return self.addSQLiteStore( + return self.addSQLiteStoreAndWait( fileURL: applicationSupportDirectory.URLByAppendingPathComponent( fileName, isDirectory: false @@ -174,7 +174,7 @@ public final class DataStack { :param: 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. */ - public func addSQLiteStore(fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult { + public func addSQLiteStoreAndWait(fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult { let coordinator = self.coordinator; if let store = coordinator.persistentStoreForURL(fileURL) { @@ -276,6 +276,7 @@ public final class DataStack { // MARK: Internal + internal let coordinator: NSPersistentStoreCoordinator internal let rootSavingContext: NSManagedObjectContext internal let mainContext: NSManagedObjectContext internal let childTransactionQueue: GCDQueue = .createSerial("com.corestore.datastack.childtransactionqueue") @@ -333,20 +334,7 @@ public final class DataStack { return returnValue } - - // MARK: Private - - private typealias EntityClassNameType = String - private typealias EntityNameType = String - private typealias ConfigurationNameType = String - - private let coordinator: NSPersistentStoreCoordinator - private let entityNameMapping: [EntityClassNameType: EntityNameType] - private let storeMetadataUpdateQueue = GCDQueue.createConcurrent("com.coreStore.persistentStoreBarrierQueue") - private var configurationStoreMapping = [ConfigurationNameType: NSPersistentStore]() - private var entityConfigurationsMapping = [EntityClassNameType: Set]() - - private func updateMetadataForPersistentStore(persistentStore: NSPersistentStore) { + internal func updateMetadataForPersistentStore(persistentStore: NSPersistentStore) { self.storeMetadataUpdateQueue.barrierAsync { @@ -358,4 +346,16 @@ public final class DataStack { } } } + + + // MARK: Private + + private typealias EntityClassNameType = String + private typealias EntityNameType = String + private typealias ConfigurationNameType = String + + private let entityNameMapping: [EntityClassNameType: EntityNameType] + private let storeMetadataUpdateQueue = GCDQueue.createConcurrent("com.coreStore.persistentStoreBarrierQueue") + private var configurationStoreMapping = [ConfigurationNameType: NSPersistentStore]() + private var entityConfigurationsMapping = [EntityClassNameType: Set]() } diff --git a/CoreStore/Setting Up/PersistentStoreResult.swift b/CoreStore/Setting Up/PersistentStoreResult.swift index 85c8466..a50f9fa 100644 --- a/CoreStore/Setting Up/PersistentStoreResult.swift +++ b/CoreStore/Setting Up/PersistentStoreResult.swift @@ -33,7 +33,7 @@ import CoreData The `PersistentStoreResult` indicates the result of initializing the persistent store. The `PersistentStoreResult` can be treated as a boolean: - let result = CoreStore.addSQLiteStore() + let result = CoreStore.addSQLiteStoreAndWait() if result { // succeeded } @@ -43,7 +43,7 @@ The `PersistentStoreResult` can be treated as a boolean: or as an `enum`, where the resulting associated object can also be inspected: - let result = CoreStore.addSQLiteStore() + let result = CoreStore.addSQLiteStoreAndWait() switch result { case .Success(let persistentStore): // persistentStore is the related NSPersistentStore instance diff --git a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj index 4139148..5c5ba13 100644 --- a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj +++ b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj @@ -24,12 +24,14 @@ B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */; }; B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3311B11DF3200F4F0C6 /* UserAccount.swift */; }; B56964C91B20AC780075EE4A /* CustomLoggerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964C81B20AC780075EE4A /* CustomLoggerViewController.swift */; }; + B56964D71B231AE90075EE4A /* StackSetupDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B56964D51B231AE90075EE4A /* StackSetupDemo.xcdatamodeld */; }; + B56964DA1B231BCA0075EE4A /* MaleAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964D91B231BCA0075EE4A /* MaleAccount.swift */; }; + B56964DC1B231BCB0075EE4A /* FemaleAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964DB1B231BCB0075EE4A /* FemaleAccount.swift */; }; + B56964DF1B2321E30075EE4A /* MigrationDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B56964DD1B2321E30075EE4A /* MigrationDemo.xcdatamodeld */; }; B583A9201AF5F542001F76AF /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B583A91B1AF5F4F4001F76AF /* CoreStore.framework */; }; B583A9211AF5F542001F76AF /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B583A91B1AF5F4F4001F76AF /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B5D9C9191B20AB1900E64F0E /* GCDKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5D9C9181B20AB1900E64F0E /* GCDKit.framework */; }; B5D9C91A1B20AB1900E64F0E /* GCDKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5D9C9181B20AB1900E64F0E /* GCDKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - B5E7240F1B11F993006FB83F /* TwitterAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E7240E1B11F993006FB83F /* TwitterAccount.swift */; }; - B5E724111B11F994006FB83F /* FacebookAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E724101B11F994006FB83F /* FacebookAccount.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -98,10 +100,13 @@ B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackSetupDemoViewController.swift; sourceTree = ""; }; B566E3311B11DF3200F4F0C6 /* UserAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserAccount.swift; sourceTree = ""; }; B56964C81B20AC780075EE4A /* CustomLoggerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomLoggerViewController.swift; sourceTree = ""; }; + B56964D61B231AE90075EE4A /* StackSetupDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = StackSetupDemo.xcdatamodel; sourceTree = ""; }; + B56964D91B231BCA0075EE4A /* MaleAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaleAccount.swift; sourceTree = ""; }; + B56964DB1B231BCB0075EE4A /* FemaleAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FemaleAccount.swift; sourceTree = ""; }; + B56964DE1B2321E30075EE4A /* MigrationDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemo.xcdatamodel; sourceTree = ""; }; + B56964E01B2326F30075EE4A /* MigrationDemoV2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemoV2.xcdatamodel; sourceTree = ""; }; B583A9141AF5F4F3001F76AF /* CoreStore.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CoreStore.xcodeproj; path = ../CoreStore.xcodeproj; sourceTree = ""; }; B5D9C9181B20AB1900E64F0E /* GCDKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = GCDKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - B5E7240E1B11F993006FB83F /* TwitterAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwitterAccount.swift; sourceTree = ""; }; - B5E724101B11F994006FB83F /* FacebookAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FacebookAccount.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -180,6 +185,8 @@ B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */, B54AAD5C1AF4D26E00848AE0 /* LaunchScreen.xib */, B54AAD501AF4D26E00848AE0 /* CoreStoreDemo.xcdatamodeld */, + B56964D51B231AE90075EE4A /* StackSetupDemo.xcdatamodeld */, + B56964DD1B2321E30075EE4A /* MigrationDemo.xcdatamodeld */, B54AAD4C1AF4D26E00848AE0 /* Supporting Files */, ); path = CoreStoreDemo; @@ -196,8 +203,8 @@ B566E3271B117AE700F4F0C6 /* Stack Setup Demo */ = { isa = PBXGroup; children = ( - B5E724101B11F994006FB83F /* FacebookAccount.swift */, - B5E7240E1B11F993006FB83F /* TwitterAccount.swift */, + B56964DB1B231BCB0075EE4A /* FemaleAccount.swift */, + B56964D91B231BCA0075EE4A /* MaleAccount.swift */, B566E3311B11DF3200F4F0C6 /* UserAccount.swift */, B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */, ); @@ -318,19 +325,21 @@ buildActionMask = 2147483647; files = ( B52977DD1B120F3B003D50A5 /* TransactionsDemoViewController.swift in Sources */, + B56964DF1B2321E30075EE4A /* MigrationDemo.xcdatamodeld in Sources */, B52977E41B121635003D50A5 /* Place.swift in Sources */, B503FAE01AFDC71700F90881 /* ObjectObserverDemoViewController.swift in Sources */, B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */, B56964C91B20AC780075EE4A /* CustomLoggerViewController.swift in Sources */, B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */, - B5E724111B11F994006FB83F /* FacebookAccount.swift in Sources */, - B5E7240F1B11F993006FB83F /* TwitterAccount.swift in Sources */, + B56964DA1B231BCA0075EE4A /* MaleAccount.swift in Sources */, B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */, B54AAD521AF4D26E00848AE0 /* CoreStoreDemo.xcdatamodeld in Sources */, B503FAE11AFDC71700F90881 /* Palette.swift in Sources */, B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */, B503FADF1AFDC71700F90881 /* ObjectListObserverDemoViewController.swift in Sources */, B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */, + B56964D71B231AE90075EE4A /* StackSetupDemo.xcdatamodeld in Sources */, + B56964DC1B231BCB0075EE4A /* FemaleAccount.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -516,6 +525,27 @@ sourceTree = ""; versionGroupType = wrapper.xcdatamodel; }; + B56964D51B231AE90075EE4A /* StackSetupDemo.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + B56964D61B231AE90075EE4A /* StackSetupDemo.xcdatamodel */, + ); + currentVersion = B56964D61B231AE90075EE4A /* StackSetupDemo.xcdatamodel */; + path = StackSetupDemo.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; + B56964DD1B2321E30075EE4A /* MigrationDemo.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + B56964E01B2326F30075EE4A /* MigrationDemoV2.xcdatamodel */, + B56964DE1B2321E30075EE4A /* MigrationDemo.xcdatamodel */, + ); + currentVersion = B56964E01B2326F30075EE4A /* MigrationDemoV2.xcdatamodel */; + path = MigrationDemo.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; /* End XCVersionGroup section */ }; rootObject = B54AAD411AF4D26E00848AE0 /* Project object */; diff --git a/CoreStoreDemo/CoreStoreDemo.xcodeproj/xcuserdata/johnestropia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/CoreStoreDemo/CoreStoreDemo.xcodeproj/xcuserdata/johnestropia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..fe2b454 --- /dev/null +++ b/CoreStoreDemo/CoreStoreDemo.xcodeproj/xcuserdata/johnestropia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/CoreStoreDemo/CoreStoreDemo/CoreStoreDemo.xcdatamodeld/CoreStoreDemo.xcdatamodel/contents b/CoreStoreDemo/CoreStoreDemo/CoreStoreDemo.xcdatamodeld/CoreStoreDemo.xcdatamodel/contents index 0b5abaa..3e02793 100644 --- a/CoreStoreDemo/CoreStoreDemo/CoreStoreDemo.xcdatamodeld/CoreStoreDemo.xcdatamodel/contents +++ b/CoreStoreDemo/CoreStoreDemo/CoreStoreDemo.xcdatamodeld/CoreStoreDemo.xcdatamodel/contents @@ -13,26 +13,14 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectListObserverDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectListObserverDemoViewController.swift index c7fd4a4..7ad6ef0 100644 --- a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectListObserverDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectListObserverDemoViewController.swift @@ -14,7 +14,7 @@ private struct Static { static let palettes: ManagedObjectListController = { - CoreStore.addSQLiteStore( + CoreStore.addSQLiteStoreAndWait( "ColorsDemo.sqlite", configuration: "ObservingDemo", resetStoreOnMigrationFailure: true diff --git a/CoreStoreDemo/CoreStoreDemo/Loggers Demo/CustomLoggerViewController.swift b/CoreStoreDemo/CoreStoreDemo/Loggers Demo/CustomLoggerViewController.swift index e2fd58a..96f59e8 100644 --- a/CoreStoreDemo/CoreStoreDemo/Loggers Demo/CustomLoggerViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/Loggers Demo/CustomLoggerViewController.swift @@ -30,7 +30,7 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger { super.viewDidLoad() - self.dataStack.addSQLiteStore("emptyStore.sqlite") + self.dataStack.addSQLiteStoreAndWait("emptyStore.sqlite") CoreStore.logger = self } @@ -104,7 +104,7 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger { } case .Some(1): - self.dataStack.addSQLiteStore("emptyStore.sqlite", configuration: "invalidStore") + self.dataStack.addSQLiteStoreAndWait("emptyStore.sqlite", configuration: "invalidStore") case .Some(2): self.dataStack.beginAsynchronous { (transaction) -> Void in diff --git a/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/.xccurrentversion b/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/.xccurrentversion new file mode 100644 index 0000000..508da66 --- /dev/null +++ b/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/.xccurrentversion @@ -0,0 +1,8 @@ + + + + + _XCCurrentVersionName + MigrationDemoV2.xcdatamodel + + diff --git a/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemo.xcdatamodel/contents b/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemo.xcdatamodel/contents new file mode 100644 index 0000000..86ab034 --- /dev/null +++ b/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemo.xcdatamodel/contents @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemoV2.xcdatamodel/contents b/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemoV2.xcdatamodel/contents new file mode 100644 index 0000000..86ab034 --- /dev/null +++ b/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemoV2.xcdatamodel/contents @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/FacebookAccount.swift b/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/FacebookAccount.swift deleted file mode 100644 index ddbe15a..0000000 --- a/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/FacebookAccount.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// FacebookAccount.swift -// CoreStoreDemo -// -// Created by John Rommel Estropia on 2015/05/24. -// Copyright (c) 2015 John Rommel Estropia. All rights reserved. -// - -import Foundation -import CoreData - - -// MARK: - FacebookAccount - -class FacebookAccount: TwitterAccount { } diff --git a/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/FemaleAccount.swift b/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/FemaleAccount.swift new file mode 100644 index 0000000..b08a832 --- /dev/null +++ b/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/FemaleAccount.swift @@ -0,0 +1,15 @@ +// +// FemaleAccount.swift +// CoreStoreDemo +// +// Created by John Rommel Estropia on 2015/06/06. +// Copyright (c) 2015 John Rommel Estropia. All rights reserved. +// + +import Foundation +import CoreData + +class FemaleAccount: UserAccount { + + +} diff --git a/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/MaleAccount.swift b/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/MaleAccount.swift new file mode 100644 index 0000000..4037e4f --- /dev/null +++ b/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/MaleAccount.swift @@ -0,0 +1,15 @@ +// +// MaleAccount.swift +// CoreStoreDemo +// +// Created by John Rommel Estropia on 2015/06/06. +// Copyright (c) 2015 John Rommel Estropia. All rights reserved. +// + +import Foundation +import CoreData + +class MaleAccount: UserAccount { + + +} diff --git a/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/StackSetupDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/StackSetupDemoViewController.swift index 4da88cc..9ee009c 100644 --- a/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/StackSetupDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/StackSetupDemoViewController.swift @@ -12,34 +12,33 @@ import CoreStore private struct Static { - static let johnConfiguration = "SetupDemo_John" - static let janeConfiguration = "SetupDemo_Jane" + static let maleConfiguration = "MaleAccounts" + static let femaleConfiguration = "FemaleAccounts" static let facebookStack: DataStack = { - let dataStack = DataStack(modelName: "CoreStoreDemo") - dataStack.addSQLiteStore( - "AccountsDemo_FB_John.sqlite", - configuration: johnConfiguration, + let dataStack = DataStack(modelName: "StackSetupDemo") + dataStack.addSQLiteStoreAndWait( + "AccountsDemo_FB_Male.sqlite", + configuration: maleConfiguration, resetStoreOnMigrationFailure: true ) - dataStack.addSQLiteStore( - "AccountsDemo_FB_Jane.sqlite", - configuration: janeConfiguration, + dataStack.addSQLiteStoreAndWait( + "AccountsDemo_FB_Female.sqlite", + configuration: femaleConfiguration, resetStoreOnMigrationFailure: true ) dataStack.beginSynchronous { (transaction) -> Void in - transaction.deleteAll(From(johnConfiguration)) - transaction.deleteAll(From(janeConfiguration)) + transaction.deleteAll(From(UserAccount)) - let account1 = transaction.create(Into(johnConfiguration)) + let account1 = transaction.create(Into(maleConfiguration)) account1.accountType = "Facebook" account1.name = "John Smith HCD" account1.friends = 42 - let account2 = transaction.create(Into(janeConfiguration)) + let account2 = transaction.create(Into(femaleConfiguration)) account2.accountType = "Facebook" account2.name = "Jane Doe HCD" account2.friends = 314 @@ -52,29 +51,28 @@ private struct Static { static let twitterStack: DataStack = { - let dataStack = DataStack(modelName: "CoreStoreDemo") - dataStack.addSQLiteStore( - "AccountsDemo_TW_John.sqlite", - configuration: johnConfiguration, + let dataStack = DataStack(modelName: "StackSetupDemo") + dataStack.addSQLiteStoreAndWait( + "AccountsDemo_TW_Male.sqlite", + configuration: maleConfiguration, resetStoreOnMigrationFailure: true ) - dataStack.addSQLiteStore( - "AccountsDemo_TW_Jane.sqlite", - configuration: janeConfiguration, + dataStack.addSQLiteStoreAndWait( + "AccountsDemo_TW_Female.sqlite", + configuration: femaleConfiguration, resetStoreOnMigrationFailure: true ) dataStack.beginSynchronous { (transaction) -> Void in - transaction.deleteAll(From(johnConfiguration)) - transaction.deleteAll(From(janeConfiguration)) + transaction.deleteAll(From(UserAccount)) - let account1 = transaction.create(Into(johnConfiguration)) + let account1 = transaction.create(Into(maleConfiguration)) account1.accountType = "Twitter" account1.name = "#johnsmith_hcd" account1.friends = 7 - let account2 = transaction.create(Into(janeConfiguration)) + let account2 = transaction.create(Into(femaleConfiguration)) account2.accountType = "Twitter" account2.name = "#janedoe_hcd" account2.friends = 100 @@ -94,14 +92,8 @@ private struct Static { class StackSetupDemoViewController: UITableViewController { let accounts = [ - [ - Static.facebookStack.fetchOne(From(Static.johnConfiguration))!, - Static.facebookStack.fetchOne(From(Static.janeConfiguration))! - ], - [ - Static.twitterStack.fetchOne(From(Static.johnConfiguration))!, - Static.twitterStack.fetchOne(From(Static.janeConfiguration))! - ] + Static.facebookStack.fetchAll(From(UserAccount)) ?? [], + Static.twitterStack.fetchAll(From(UserAccount)) ?? [] ] @@ -169,11 +161,11 @@ class StackSetupDemoViewController: UITableViewController { switch section { case 0: - let count = Static.facebookStack.fetchCount(From(UserAccount)) ?? 0 + let count = self.accounts[section].count return "Facebook Accounts (\(count) users)" case 1: - let count = Static.twitterStack.fetchCount(From(UserAccount)) ?? 0 + let count = self.accounts[section].count return "Twitter Accounts (\(count) users)" default: diff --git a/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/TwitterAccount.swift b/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/TwitterAccount.swift deleted file mode 100644 index 2c6deeb..0000000 --- a/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/TwitterAccount.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// TwitterAccount.swift -// CoreStoreDemo -// -// Created by John Rommel Estropia on 2015/05/24. -// Copyright (c) 2015 John Rommel Estropia. All rights reserved. -// - -import Foundation -import CoreData - - -// MARK: - TwitterAccount - -class TwitterAccount: UserAccount { } diff --git a/CoreStoreDemo/CoreStoreDemo/StackSetupDemo.xcdatamodeld/StackSetupDemo.xcdatamodel/contents b/CoreStoreDemo/CoreStoreDemo/StackSetupDemo.xcdatamodeld/StackSetupDemo.xcdatamodel/contents new file mode 100644 index 0000000..37b3cb2 --- /dev/null +++ b/CoreStoreDemo/CoreStoreDemo/StackSetupDemo.xcdatamodeld/StackSetupDemo.xcdatamodel/contents @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift index 79a11d2..b7143f8 100644 --- a/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift @@ -18,7 +18,7 @@ private struct Static { static let placeController: ManagedObjectController = { - CoreStore.addSQLiteStore( + CoreStore.addSQLiteStoreAndWait( "PlaceDemo.sqlite", configuration: "TransactionsDemo", resetStoreOnMigrationFailure: true diff --git a/CoreStoreTests/CoreStoreTests.swift b/CoreStoreTests/CoreStoreTests.swift index ace963b..0107c78 100644 --- a/CoreStoreTests/CoreStoreTests.swift +++ b/CoreStoreTests/CoreStoreTests.swift @@ -47,7 +47,7 @@ class CoreStoreTests: XCTestCase { CoreStore.defaultStack = stack XCTAssert(CoreStore.defaultStack === stack, "CoreStore.defaultStack === stack") - switch stack.addSQLiteStore("ConfigStore1.sqlite", configuration: "Config1", resetStoreOnMigrationFailure: true){ + switch stack.addSQLiteStoreAndWait("ConfigStore1.sqlite", configuration: "Config1", resetStoreOnMigrationFailure: true){ case .Failure(let error): XCTFail(error.description) @@ -56,7 +56,7 @@ class CoreStoreTests: XCTestCase { break } - switch stack.addSQLiteStore("ConfigStore2.sqlite", configuration: "Config2", resetStoreOnMigrationFailure: true){ + switch stack.addSQLiteStoreAndWait("ConfigStore2.sqlite", configuration: "Config2", resetStoreOnMigrationFailure: true){ case .Failure(let error): XCTFail(error.description) diff --git a/README.md b/README.md index 7328a02..e5db938 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Simple, elegant, and smart Core Data programming with Swift Quick-setup: ```swift -CoreStore.addSQLiteStore("MyStore.sqlite") +CoreStore.addSQLiteStoreAndWait("MyStore.sqlite") ``` Simple transactions: @@ -107,7 +107,7 @@ This allows for a butter-smooth main thread, while still taking advantage of saf ## Setting up The simplest way to initialize CoreStore is to add a default store to the default stack: ```swift -CoreStore.addSQLiteStore() +CoreStore.addSQLiteStoreAndWait() ``` This one-liner does the following: - Triggers the lazy-initialization of `CoreStore.defaultStack` with a default `DataStack` @@ -126,7 +126,7 @@ case .Failure(let error): // error is an NSError instance println("Failed creating an in-memory store with error: \(error.description)" } -switch dataStack.addSQLiteStore( +switch dataStack.addSQLiteStoreAndWait( fileURL: sqliteFileURL, // set the target file URL for the sqlite file configuration: "Config2", // use entities from the "Config2" configuration in the .xcdatamodeld file automigrating: true, // automatically run lightweight migrations or entity policy migrations when needed @@ -146,7 +146,7 @@ class MyViewController: UIViewController { let dataStack = DataStack(modelName: "MyModel") override func viewDidLoad() { super.viewDidLoad() - self.dataStack.addSQLiteStore() + self.dataStack.addSQLiteStoreAndWait() } func methodToBeCalledLaterOn() { let objects = self.dataStack.fetchAll(From(MyEntity)) @@ -159,7 +159,7 @@ The difference is when you set the stack as the `CoreStore.defaultStack`, you ca class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - CoreStore.addSQLiteStore() + CoreStore.addSQLiteStoreAndWait() } func methodToBeCalledLaterOn() { let objects = CoreStore.fetchAll(From(MyEntity))