diff --git a/CoreStore.xcodeproj/project.pbxproj b/CoreStore.xcodeproj/project.pbxproj index a077ee0..1f29e13 100644 --- a/CoreStore.xcodeproj/project.pbxproj +++ b/CoreStore.xcodeproj/project.pbxproj @@ -141,10 +141,6 @@ B52DD1CC1BE1F94D00949AFE /* CoreStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F03A53F19C5C6DA005002A5 /* CoreStoreTests.swift */; }; B52DD1CD1BE1F94D00949AFE /* TestEntity1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D372851A39CDDB00F583D9 /* TestEntity1.swift */; }; B52DD1CE1BE1F94D00949AFE /* TestEntity2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D5E0CE1A4D6AAB006468AF /* TestEntity2.swift */; }; - B546F9531C95529D00D5AC55 /* LocalStorageOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9521C95529D00D5AC55 /* LocalStorageOptions.swift */; }; - B546F9541C95529D00D5AC55 /* LocalStorageOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9521C95529D00D5AC55 /* LocalStorageOptions.swift */; }; - B546F9551C95529D00D5AC55 /* LocalStorageOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9521C95529D00D5AC55 /* LocalStorageOptions.swift */; }; - B546F9561C95529D00D5AC55 /* LocalStorageOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9521C95529D00D5AC55 /* LocalStorageOptions.swift */; }; B546F9581C99B17400D5AC55 /* CSCoreStore+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9571C99B17400D5AC55 /* CSCoreStore+Setup.swift */; }; B546F9591C99B17400D5AC55 /* CSCoreStore+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9571C99B17400D5AC55 /* CSCoreStore+Setup.swift */; }; B546F95A1C99B17400D5AC55 /* CSCoreStore+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9571C99B17400D5AC55 /* CSCoreStore+Setup.swift */; }; @@ -153,6 +149,18 @@ B546F95E1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F95C1C9A12B800D5AC55 /* CSSQliteStore.swift */; }; B546F95F1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F95C1C9A12B800D5AC55 /* CSSQliteStore.swift */; }; B546F9601C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F95C1C9A12B800D5AC55 /* CSSQliteStore.swift */; }; + B546F9641C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9631C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift */; }; + B546F9651C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9631C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift */; }; + B546F9661C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9631C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift */; }; + B546F9671C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9631C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift */; }; + B546F9691C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9681C9AF26D00D5AC55 /* CSInMemoryStore.swift */; }; + B546F96A1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9681C9AF26D00D5AC55 /* CSInMemoryStore.swift */; }; + B546F96B1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9681C9AF26D00D5AC55 /* CSInMemoryStore.swift */; }; + B546F96C1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9681C9AF26D00D5AC55 /* CSInMemoryStore.swift */; }; + B546F96E1C9B14AC00D5AC55 /* CSStorageInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F96D1C9B14AC00D5AC55 /* CSStorageInterface.swift */; }; + B546F96F1C9B14AC00D5AC55 /* CSStorageInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F96D1C9B14AC00D5AC55 /* CSStorageInterface.swift */; }; + B546F9701C9B14AC00D5AC55 /* CSStorageInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F96D1C9B14AC00D5AC55 /* CSStorageInterface.swift */; }; + B546F9711C9B14AC00D5AC55 /* CSStorageInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F96D1C9B14AC00D5AC55 /* CSStorageInterface.swift */; }; B54A6A551BA15F2A007870FD /* FetchedResultsControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */; }; B5598BCC1BE2093D0092EFCE /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; }; B56007111B3F6BD500A9A8F9 /* Into.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007101B3F6BD500A9A8F9 /* Into.swift */; }; @@ -367,9 +375,11 @@ B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFetchedResultsController+Convenience.swift"; sourceTree = ""; }; B52DD1741BE1F8CC00949AFE /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B52DD17D1BE1F8CC00949AFE /* CoreStoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreStoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - B546F9521C95529D00D5AC55 /* LocalStorageOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalStorageOptions.swift; sourceTree = ""; }; B546F9571C99B17400D5AC55 /* CSCoreStore+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSCoreStore+Setup.swift"; sourceTree = ""; }; B546F95C1C9A12B800D5AC55 /* CSSQliteStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSQliteStore.swift; sourceTree = ""; }; + B546F9631C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSLegacySQLiteStore.swift; sourceTree = ""; }; + B546F9681C9AF26D00D5AC55 /* CSInMemoryStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSInMemoryStore.swift; sourceTree = ""; }; + B546F96D1C9B14AC00D5AC55 /* CSStorageInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSStorageInterface.swift; sourceTree = ""; }; B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchedResultsControllerDelegate.swift; sourceTree = ""; }; B5548CD51BD65AE00077652A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; B5548CD71BD65AE50077652A /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; }; @@ -645,7 +655,10 @@ B546F9621C9A140E00D5AC55 /* StorageInterfaces */ = { isa = PBXGroup; children = ( + B546F96D1C9B14AC00D5AC55 /* CSStorageInterface.swift */, + B546F9681C9AF26D00D5AC55 /* CSInMemoryStore.swift */, B546F95C1C9A12B800D5AC55 /* CSSQliteStore.swift */, + B546F9631C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift */, ); name = StorageInterfaces; sourceTree = ""; @@ -802,7 +815,6 @@ B5FE4DA01C84818B00FA6A91 /* StorageInterfaces */ = { isa = PBXGroup; children = ( - B546F9521C95529D00D5AC55 /* LocalStorageOptions.swift */, B5FE4DA11C8481E100FA6A91 /* StorageInterface.swift */, B5FE4DA61C84FB4400FA6A91 /* InMemoryStore.swift */, B5FE4DAB1C85D44E00FA6A91 /* SQLiteStore.swift */, @@ -1115,10 +1127,12 @@ B5DBE2D21C991B3E00B5CEFA /* CSDataStack.swift in Sources */, B50392F91C478FF3009900CA /* NSManagedObject+Transaction.swift in Sources */, B5202CFA1C04688100DED140 /* NSFetchedResultsController+Convenience.swift in Sources */, + B546F96E1C9B14AC00D5AC55 /* CSStorageInterface.swift in Sources */, B5E84EE11AFF84500064E85B /* SetupResult.swift in Sources */, B5E84F251AFF84860064E85B /* ObjectObserver.swift in Sources */, B5E84F2F1AFF849C0064E85B /* NotificationObserver.swift in Sources */, B5F1DA8D1B9AA97D007C5CBB /* ImportableObject.swift in Sources */, + B546F9641C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift in Sources */, B56965241B356B820075EE4A /* MigrationResult.swift in Sources */, B5FE4DAC1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */, 2F291E2719C6D3CF007AF63F /* CoreStore.swift in Sources */, @@ -1129,7 +1143,6 @@ B5FEC18E1C9166E200532541 /* NSPersistentStore+Setup.swift in Sources */, B5E84EDF1AFF84500064E85B /* DataStack.swift in Sources */, B59AFF411C6593E400C0ABE2 /* NSPersistentStoreCoordinator+Setup.swift in Sources */, - B546F9531C95529D00D5AC55 /* LocalStorageOptions.swift in Sources */, B5E834BB1B7691F3001D3D50 /* Functions.swift in Sources */, B5E84F231AFF84860064E85B /* ListMonitor.swift in Sources */, B5E84EF71AFF846E0064E85B /* UnsafeDataTransaction.swift in Sources */, @@ -1150,6 +1163,7 @@ B5E84F201AFF84860064E85B /* DataStack+Observing.swift in Sources */, B5E84EF81AFF846E0064E85B /* CoreStore+Transaction.swift in Sources */, B5E84F301AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift in Sources */, + B546F9691C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, B5E84F211AFF84860064E85B /* CoreStore+Observing.swift in Sources */, B5FE4DA71C84FB4400FA6A91 /* InMemoryStore.swift in Sources */, B5E834B91B76311F001D3D50 /* BaseDataTransaction+Importing.swift in Sources */, @@ -1207,10 +1221,12 @@ B5DBE2D31C991B3E00B5CEFA /* CSDataStack.swift in Sources */, 82BA18B41C4BBD3900A0916E /* BaseDataTransaction+Importing.swift in Sources */, 82BA18CA1C4BBD5900A0916E /* MigrationResult.swift in Sources */, + B546F96F1C9B14AC00D5AC55 /* CSStorageInterface.swift in Sources */, 82BA18C11C4BBD5300A0916E /* CoreStore+Observing.swift in Sources */, 82BA18BC1C4BBD4A00A0916E /* OrderBy.swift in Sources */, 82BA18B01C4BBD3100A0916E /* NSManagedObject+Transaction.swift in Sources */, 82BA18D41C4BBD7100A0916E /* NSManagedObjectContext+Querying.swift in Sources */, + B546F9651C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift in Sources */, 82BA18D51C4BBD7100A0916E /* NSManagedObjectContext+Setup.swift in Sources */, B5FE4DA31C8481E100FA6A91 /* StorageInterface.swift in Sources */, 82BA18C91C4BBD5900A0916E /* MigrationType.swift in Sources */, @@ -1221,7 +1237,6 @@ B5FEC18F1C9166E600532541 /* NSPersistentStore+Setup.swift in Sources */, 82BA18B71C4BBD3F00A0916E /* CoreStore+Querying.swift in Sources */, 82BA18A41C4BBD2200A0916E /* SetupResult.swift in Sources */, - B546F9541C95529D00D5AC55 /* LocalStorageOptions.swift in Sources */, 82BA18AA1C4BBD3100A0916E /* BaseDataTransaction.swift in Sources */, 82BA18A91C4BBD3100A0916E /* Into.swift in Sources */, 82BA18D11C4BBD7100A0916E /* NotificationObserver.swift in Sources */, @@ -1242,6 +1257,7 @@ 82BA18B51C4BBD3F00A0916E /* BaseDataTransaction+Querying.swift in Sources */, 82BA18D31C4BBD7100A0916E /* NSManagedObjectContext+CoreStore.swift in Sources */, 82BA18AD1C4BBD3100A0916E /* UnsafeDataTransaction.swift in Sources */, + B546F96A1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, 82BA18A81C4BBD2900A0916E /* CoreStoreLogger.swift in Sources */, 82BA18B81C4BBD4200A0916E /* ClauseTypes.swift in Sources */, 82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */, @@ -1303,16 +1319,17 @@ B52DD1BC1BE1F94000949AFE /* MigrationResult.swift in Sources */, B52DD19D1BE1F92C00949AFE /* BaseDataTransaction.swift in Sources */, B52DD1B81BE1F94000949AFE /* DataStack+Migration.swift in Sources */, - B546F9561C95529D00D5AC55 /* LocalStorageOptions.swift in Sources */, B52DD1A51BE1F92F00949AFE /* ImportableUniqueObject.swift in Sources */, B52DD19C1BE1F92C00949AFE /* Into.swift in Sources */, B5FE4DA51C8481E100FA6A91 /* StorageInterface.swift in Sources */, + B546F9711C9B14AC00D5AC55 /* CSStorageInterface.swift in Sources */, B5FE4DAA1C84FB4400FA6A91 /* InMemoryStore.swift in Sources */, B52DD1AF1BE1F93900949AFE /* GroupBy.swift in Sources */, B52DD1B01BE1F93900949AFE /* Tweak.swift in Sources */, B52DD1CA1BE1F94600949AFE /* NSManagedObjectModel+Setup.swift in Sources */, B52DD1A41BE1F92F00949AFE /* ImportableObject.swift in Sources */, B52DD1AE1BE1F93900949AFE /* OrderBy.swift in Sources */, + B546F9671C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift in Sources */, B52DD1BA1BE1F94000949AFE /* MigrationChain.swift in Sources */, B50392FB1C479640009900CA /* NSManagedObject+Transaction.swift in Sources */, B52DD1A31BE1F92C00949AFE /* SaveResult.swift in Sources */, @@ -1321,6 +1338,7 @@ B52DD1C11BE1F94600949AFE /* Functions.swift in Sources */, B52DD19A1BE1F92800949AFE /* CoreStore+Logging.swift in Sources */, B52DD1A71BE1F93200949AFE /* BaseDataTransaction+Querying.swift in Sources */, + B546F96C1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, B52DD1C61BE1F94600949AFE /* NSManagedObjectContext+CoreStore.swift in Sources */, B52DD1A21BE1F92C00949AFE /* CoreStore+Transaction.swift in Sources */, B52DD1A01BE1F92C00949AFE /* UnsafeDataTransaction.swift in Sources */, @@ -1380,10 +1398,12 @@ B5DBE2D41C991B3E00B5CEFA /* CSDataStack.swift in Sources */, B56321AF1BD6521C006C9394 /* NSFileManager+Setup.swift in Sources */, B50392FA1C47963F009900CA /* NSManagedObject+Transaction.swift in Sources */, + B546F9701C9B14AC00D5AC55 /* CSStorageInterface.swift in Sources */, B56321971BD65216006C9394 /* Select.swift in Sources */, B56321AB1BD6521C006C9394 /* FetchedResultsControllerDelegate.swift in Sources */, B56321821BD65216006C9394 /* SetupResult.swift in Sources */, B563219C1BD65216006C9394 /* SectionBy.swift in Sources */, + B546F9661C9AEFBA00D5AC55 /* CSLegacySQLiteStore.swift in Sources */, B56321B21BD6521C006C9394 /* NSManagedObjectContext+Querying.swift in Sources */, B5FE4DA41C8481E100FA6A91 /* StorageInterface.swift in Sources */, B56321B31BD6521C006C9394 /* NSManagedObjectContext+Setup.swift in Sources */, @@ -1394,7 +1414,6 @@ B5FEC1901C9166E700532541 /* NSPersistentStore+Setup.swift in Sources */, B56321A11BD65216006C9394 /* ListMonitor.swift in Sources */, B56321881BD65216006C9394 /* BaseDataTransaction.swift in Sources */, - B546F9551C95529D00D5AC55 /* LocalStorageOptions.swift in Sources */, B56321A31BD65216006C9394 /* DataStack+Migration.swift in Sources */, B56321901BD65216006C9394 /* ImportableUniqueObject.swift in Sources */, B56321871BD65216006C9394 /* Into.swift in Sources */, @@ -1415,6 +1434,7 @@ B56321921BD65216006C9394 /* BaseDataTransaction+Querying.swift in Sources */, B56321B11BD6521C006C9394 /* NSManagedObjectContext+CoreStore.swift in Sources */, B563218D1BD65216006C9394 /* CoreStore+Transaction.swift in Sources */, + B546F96B1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, B563218B1BD65216006C9394 /* UnsafeDataTransaction.swift in Sources */, B56321A61BD65216006C9394 /* MigrationType.swift in Sources */, B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */, diff --git a/CoreStoreDemo/CoreStoreDemo/CoreStoreDemo.xcdatamodeld/CoreStoreDemo.xcdatamodel/contents b/CoreStoreDemo/CoreStoreDemo/CoreStoreDemo.xcdatamodeld/CoreStoreDemo.xcdatamodel/contents index 0198ef1..40c216e 100644 --- a/CoreStoreDemo/CoreStoreDemo/CoreStoreDemo.xcdatamodeld/CoreStoreDemo.xcdatamodel/contents +++ b/CoreStoreDemo/CoreStoreDemo/CoreStoreDemo.xcdatamodeld/CoreStoreDemo.xcdatamodel/contents @@ -1,5 +1,5 @@ - + diff --git a/CoreStoreTests/BridgingTests.m b/CoreStoreTests/BridgingTests.m index acfb196..2789335 100644 --- a/CoreStoreTests/BridgingTests.m +++ b/CoreStoreTests/BridgingTests.m @@ -24,8 +24,10 @@ // #import "BridgingTests.h" +#import + +@import CoreData; -@import CoreStore; @implementation BridgingTests @@ -39,6 +41,15 @@ [CSCoreStore setDefaultStack:dataStack]; XCTAssertTrue([dataStack isEqual:[CSCoreStore defaultStack]]); + + CSInMemoryStore *storage = [CSCoreStore + addStorageAndWait:[CSInMemoryStore new] + error:nil]; + XCTAssertNotNil(storage); + XCTAssertEqual([[storage class] storeType], [CSInMemoryStore storeType]); + XCTAssertEqual([[storage class] storeType], NSInMemoryStoreType); + XCTAssertNil(storage.configuration); + XCTAssertNil(storage.storeOptions); } @end diff --git a/Sources/ObjectiveC/CSCoreStore+Setup.swift b/Sources/ObjectiveC/CSCoreStore+Setup.swift index e4517b4..ba81493 100644 --- a/Sources/ObjectiveC/CSCoreStore+Setup.swift +++ b/Sources/ObjectiveC/CSCoreStore+Setup.swift @@ -40,7 +40,7 @@ public extension CSCoreStore { /** Creates an `CSSQLiteStore` with default parameters and adds it to the `defaultStack`. This method blocks until completion. ``` - try CSCoreStore.addStorageAndWait() + CSSQLiteStore *storage = [CSCoreStore addStorageAndWaitAndReturnError:&error]; ``` - returns: the local SQLite storage added to the `defaultStack` @@ -54,17 +54,19 @@ public extension CSCoreStore { /** Adds a `StorageInterface` to the `defaultStack` and blocks until completion. ``` - try CoreStore.addStorageAndWait(InMemoryStore(configuration: "Config1")) + CSInMemoryStore *storage = [CoreStore + addStorageAndWait: [[InMemoryStore alloc] initWithConfiguration: @"Config1"] + error: &error]; ``` - parameter storage: the `StorageInterface` - returns: the `StorageInterface` added to the `defaultStack` */ -// @objc -// public static func addStorageAndWait(storage: StorageInterface) throws -> StorageInterface { -// -// return try self.defaultStack.swift.addStorageAndWait(storage) -// } + @objc + public static func addStorageAndWait(storage: CSInMemoryStore) throws -> CSInMemoryStore { + + return try CoreStore.defaultStack.addStorageAndWait(storage.swift).objc + } /** Creates a `LocalStorageface` of the specified store type with default values and adds it to the `defaultStack`. This method blocks until completion. diff --git a/Sources/ObjectiveC/CSDataStack.swift b/Sources/ObjectiveC/CSDataStack.swift index a71dc96..638d2c2 100644 --- a/Sources/ObjectiveC/CSDataStack.swift +++ b/Sources/ObjectiveC/CSDataStack.swift @@ -33,7 +33,7 @@ extension DataStack: CoreStoreBridgeable { // MARK: CoreStoreBridgeable - public typealias NativeType = CSDataStack + public typealias ObjCType = CSDataStack } @@ -62,12 +62,12 @@ public final class CSDataStack: NSObject, CoreStoreBridge { - parameter versionChain: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack. */ @objc - public convenience init(modelName: String = DataStack.applicationName, bundle: NSBundle = NSBundle.mainBundle(), versionChain: [String]? = nil) { + public convenience init(modelName: String?, bundle: NSBundle?, versionChain: [String]?) { self.init( DataStack( - modelName: modelName, - bundle: bundle, + modelName: modelName ?? DataStack.applicationName, + bundle: bundle ?? NSBundle.mainBundle(), migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil ) ) @@ -81,12 +81,12 @@ public final class CSDataStack: NSObject, CoreStoreBridge { - parameter versionTree: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack. */ @objc - public convenience init(modelName: String = DataStack.applicationName, bundle: NSBundle = NSBundle.mainBundle(), versionTree: [String: String]? = nil) { + public convenience init(modelName: String?, bundle: NSBundle?, versionTree: [String: String]?) { self.init( DataStack( - modelName: modelName, - bundle: bundle, + modelName: modelName ?? DataStack.applicationName, + bundle: bundle ?? NSBundle.mainBundle(), migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil ) ) @@ -99,7 +99,7 @@ public final class CSDataStack: NSObject, CoreStoreBridge { - parameter versionChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack. */ @objc - public convenience init(model: NSManagedObjectModel, versionChain: [String]? = nil) { + public convenience init(model: NSManagedObjectModel, versionChain: [String]?) { self.init( DataStack( @@ -116,7 +116,7 @@ public final class CSDataStack: NSObject, CoreStoreBridge { - parameter versionTree: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack. */ @objc - public convenience init(model: NSManagedObjectModel, versionTree: [String]? = nil) { + public convenience init(model: NSManagedObjectModel, versionTree: [String]?) { self.init( DataStack( diff --git a/Sources/ObjectiveC/CSInMemoryStore.swift b/Sources/ObjectiveC/CSInMemoryStore.swift new file mode 100644 index 0000000..3334c2f --- /dev/null +++ b/Sources/ObjectiveC/CSInMemoryStore.swift @@ -0,0 +1,121 @@ +// +// CSInMemoryStore.swift +// CoreStore +// +// Copyright © 2016 John Rommel Estropia +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +import Foundation +import CoreData + + +// MARK: - InMemoryStore + +extension InMemoryStore: CoreStoreBridgeable { + + // MARK: CoreStoreBridgeable + + public typealias ObjCType = CSInMemoryStore +} + + +// MARK: - CSInMemoryStore + +/** + The `CSInMemoryStore` serves as the Objective-C bridging type for `InMemoryStore`. + */ +@objc +public final class CSInMemoryStore: NSObject, CoreStoreBridge { + + /** + Initializes a `CSInMemoryStore` for the specified configuration + + - parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. + */ + @objc + public convenience init(configuration: String?) { + + self.init(InMemoryStore(configuration: configuration)) + } + + /** + Initializes a `CSInMemoryStore` with the "Default" configuration + */ + @objc + public convenience override init() { + + self.init(InMemoryStore()) + } + + + // MARK: StorageInterface + + /** + The string identifier for the `NSPersistentStore`'s `type` property. For `CSInMemoryStore`s, this is always set to `NSInMemoryStoreType`. + */ + @objc + public static let storeType = NSInMemoryStoreType + + /** + The configuration name in the model file + */ + @objc + public var configuration: String? { + + return self.swift.configuration + } + + /** + The options dictionary for the `NSPersistentStore`. For `CSInMemoryStore`s, this is always set to `nil`. + */ + @objc + public var storeOptions: [String: AnyObject]? { + + return self.swift.storeOptions + } + + + // MARK: NSObject + + public override var hash: Int { + + return ObjectIdentifier(self.swift).hashValue + } + + public override func isEqual(object: AnyObject?) -> Bool { + + guard let object = object as? CSInMemoryStore else { + + return false + } + return self.swift === object.swift + } + + + // MARK: CoreStoreBridge + + public let swift: InMemoryStore + + public required init(_ swiftObject: InMemoryStore) { + + self.swift = swiftObject + } +} diff --git a/Sources/ObjectiveC/CSLegacySQLiteStore.swift b/Sources/ObjectiveC/CSLegacySQLiteStore.swift new file mode 100644 index 0000000..40772f2 --- /dev/null +++ b/Sources/ObjectiveC/CSLegacySQLiteStore.swift @@ -0,0 +1,75 @@ +// +// CSLegacySQLiteStore.swift +// CoreStore +// +// Copyright © 2016 John Rommel Estropia +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +import Foundation +import CoreData + + +// MARK: - LegacySQLiteStore + +extension LegacySQLiteStore: CoreStoreBridgeable { + + // MARK: CoreStoreBridgeable + + public typealias ObjCType = CSLegacySQLiteStore +} + + +// MARK: - CSSQLiteStore + +/** + The `CSLegacySQLiteStore` serves as the Objective-C bridging type for `LegacySQLiteStore`. + */ +@objc +public final class CSLegacySQLiteStore: NSObject, CoreStoreBridge { + + + + // MARK: NSObject + + public override var hash: Int { + + return ObjectIdentifier(self.swift).hashValue + } + + public override func isEqual(object: AnyObject?) -> Bool { + + guard let object = object as? CSLegacySQLiteStore else { + + return false + } + return self.swift === object.swift + } + + + // MARK: CoreStoreBridge + + public let swift: LegacySQLiteStore + + public required init(_ swiftObject: LegacySQLiteStore) { + + self.swift = swiftObject + } +} diff --git a/Sources/ObjectiveC/CSSQliteStore.swift b/Sources/ObjectiveC/CSSQliteStore.swift index 8d1c840..3fe32a1 100644 --- a/Sources/ObjectiveC/CSSQliteStore.swift +++ b/Sources/ObjectiveC/CSSQliteStore.swift @@ -33,18 +33,139 @@ extension SQLiteStore: CoreStoreBridgeable { // MARK: CoreStoreBridgeable - public typealias NativeType = CSSQLiteStore + public typealias ObjCType = CSSQLiteStore } // MARK: - CSSQLiteStore /** - The `CSSQLiteStore` serves as the Objective-C bridging type for `SQLiteStore`. + The `CSSQLiteStore` serves as the Objective-C bridging type for `CSSQLiteStore`. */ @objc public final class CSSQLiteStore: NSObject, CoreStoreBridge { + /** + Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `CSDataStack`'s `addStorage()` methods, a new SQLite file will be created if it does not exist. + + - parameter fileURL: the local file URL for the target SQLite persistent store. 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: a list of `NSBundle`s from which to search mapping models for migration. + - parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `.None`. + */ + @objc + public convenience init(fileURL: NSURL, configuration: String?, mappingModelBundles: [NSBundle]?, localStorageOptions: CSLocalStorageOptions) { + + self.init( + SQLiteStore( + fileURL: fileURL, + configuration: configuration, + mappingModelBundles: mappingModelBundles ?? NSBundle.allBundles(), + localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions.rawValue) + ) + ) + } + + /** + Initializes an SQLite store interface from the given SQLite file name. When this instance is passed to the `CSDataStack`'s `addStorage()` methods, a new SQLite file will be created if it does not exist. + - Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`. + + - parameter fileName: the local filename for the SQLite persistent store in the "Application Support/" directory (or the "Caches/" directory on tvOS). 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: a list of `NSBundle`s from which to search mapping models for migration + - parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `.None`. + */ + @objc + public convenience init(fileName: String, configuration: String?, mappingModelBundles: [NSBundle]?, localStorageOptions: CSLocalStorageOptions) { + + self.init( + SQLiteStore( + fileName: fileName, + configuration: configuration, + mappingModelBundles: mappingModelBundles ?? NSBundle.allBundles(), + localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions.rawValue) + ) + ) + } + + /** + Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a ".sqlite" file in the "Application Support/" directory (or the "Caches/" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `.AllowProgresiveMigration`. + - Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`. + */ + @objc + public convenience override init() { + + self.init(SQLiteStore()) + } + + + // MAKR: CSLocalStorage + + /** + The `NSURL` that points to the SQLite file + */ + @objc + public var fileURL: NSURL { + + return self.swift.fileURL + } + + /** + The `NSBundle`s from which to search mapping models for migrations + */ + @objc + public var mappingModelBundles: [NSBundle] { + + return self.swift.mappingModelBundles + } + + /** + Options that tell the `CSDataStack` how to setup the persistent store + */ + @objc + public var localStorageOptions: CSLocalStorageOptions { + + // TODO: allow options + return CSLocalStorageOptions(rawValue: self.swift.localStorageOptions.rawValue) ?? .None + } + + + // MARK: CSStorageInterface + + /** + The string identifier for the `NSPersistentStore`'s `type` property. For `CSSQLiteStore`s, this is always set to `NSSQLiteStoreType`. + */ + @objc + public static let storeType = NSSQLiteStoreType + + /** + The configuration name in the model file + */ + public var configuration: String? { + + return self.swift.configuration + } + + /** + The options dictionary for the `NSPersistentStore`. For `CSSQLiteStore`s, this is always set to + ``` + [NSSQLitePragmasOption: ["journal_mode": "WAL"]] + ``` + */ + @objc + public var storeOptions: [String: AnyObject]? { + + return self.swift.storeOptions + } + + /** + Called by the `CSDataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. For `CSSQLiteStore`, this converts the database's WAL journaling mode to DELETE before deleting the file. + */ + @objc + public func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel) throws { + + try self.swift.eraseStorageAndWait(soureModel: soureModel) + } // MARK: NSObject diff --git a/Sources/ObjectiveC/CSStorageInterface.swift b/Sources/ObjectiveC/CSStorageInterface.swift new file mode 100644 index 0000000..1e6383b --- /dev/null +++ b/Sources/ObjectiveC/CSStorageInterface.swift @@ -0,0 +1,98 @@ +// +// CSStorageInterface.swift +// CoreStore +// +// Created by John Rommel Estropia on 2016/03/18. +// Copyright © 2016 John Rommel Estropia. All rights reserved. +// + +import UIKit + +/** + The `CSStorageInterface` serves as the Objective-C bridging type for `StorageInterface`. + */ +@objc +public protocol CSStorageInterface { + + /** + The string identifier for the `NSPersistentStore`'s `type` property. This is the same string CoreStore will use to create the `NSPersistentStore` from the `NSPersistentStoreCoordinator`'s `addPersistentStoreWithType(...)` method. + */ + @objc + static var storeType: String { get } + + /** + The configuration name in the model file + */ + @objc + var configuration: String? { get } + + /** + The options dictionary for the `NSPersistentStore` + */ + @objc + var storeOptions: [String: AnyObject]? { get } +} + + +// MARK: - CSLocalStorageOptions + +/** + The `CSLocalStorageOptions` provides settings that tells the `CSDataStack` how to setup the persistent store for `CSLocalStorage` implementers. + */ +@objc +public enum CSLocalStorageOptions: Int { + + /** + Tells the `DataStack` that the store should not be migrated or recreated, and should simply fail on model mismatch + */ + case None = 0 + + /** + Tells the `DataStack` to delete and recreate the store on model mismatch, otherwise exceptions will be thrown on failure instead + */ + case RecreateStoreOnModelMismatch = 1 + + /** + Tells the `DataStack` to prevent progressive migrations for the store + */ + case PreventProgressiveMigration = 2 + + /** + Tells the `DataStack` to allow lightweight migration for the store when added synchronously + */ + case AllowSynchronousLightweightMigration = 4 +} + + +// MARK: - CSLocalStorage + +/** + The `CSLocalStorage` serves as the Objective-C bridging type for `LocalStorage`. + */ +@objc +public protocol CSLocalStorage: CSStorageInterface { + + /** + The `NSURL` that points to the store file + */ + @objc + var fileURL: NSURL { get } + + /** + The `NSBundle`s from which to search mapping models for migrations + */ + @objc + var mappingModelBundles: [NSBundle] { get } + + /** + Options that tell the `DataStack` how to setup the persistent store + */ + @objc + var localStorageOptions: CSLocalStorageOptions { get } + + /** + Called by the `CSDataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. Implementers can use the `sourceModel` to perform necessary store operations. (SQLite stores for example, can convert WAL journaling mode to DELETE before deleting) + */ + @objc + func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel) throws +} diff --git a/Sources/ObjectiveC/CoreStoreBridge.swift b/Sources/ObjectiveC/CoreStoreBridge.swift index 94bce22..f6cd6fd 100644 --- a/Sources/ObjectiveC/CoreStoreBridge.swift +++ b/Sources/ObjectiveC/CoreStoreBridge.swift @@ -36,10 +36,10 @@ public protocol CoreStoreBridge: class, AnyObject { public protocol CoreStoreBridgeable: _ObjectiveCBridgeable { - associatedtype NativeType: CoreStoreBridge + associatedtype ObjCType: CoreStoreBridge } -public extension CoreStoreBridgeable where NativeType.SwiftType == Self { +public extension CoreStoreBridgeable where Self == ObjCType.SwiftType { static func _isBridgedToObjectiveC() -> Bool { @@ -48,26 +48,26 @@ public extension CoreStoreBridgeable where NativeType.SwiftType == Self { static func _getObjectiveCType() -> Any.Type { - return NativeType.self + return ObjCType.self } - func _bridgeToObjectiveC() -> NativeType { + func _bridgeToObjectiveC() -> ObjCType { - return NativeType(self) + return ObjCType(self) } - static func _forceBridgeFromObjectiveC(source: NativeType, inout result: Self?) { + static func _forceBridgeFromObjectiveC(source: ObjCType, inout result: ObjCType.SwiftType?) { result = source.swift } - static func _conditionallyBridgeFromObjectiveC(source: NativeType, inout result: Self?) -> Bool { + static func _conditionallyBridgeFromObjectiveC(source: ObjCType, inout result: ObjCType.SwiftType?) -> Bool { - self._forceBridgeFromObjectiveC(source, result: &result) + result = source.swift return true } - var objc: NativeType { + var objc: ObjCType { return self._bridgeToObjectiveC() } diff --git a/Sources/Setting Up/StorageInterfaces/InMemoryStore.swift b/Sources/Setting Up/StorageInterfaces/InMemoryStore.swift index 09b8b88..0406ea6 100644 --- a/Sources/Setting Up/StorageInterfaces/InMemoryStore.swift +++ b/Sources/Setting Up/StorageInterfaces/InMemoryStore.swift @@ -31,14 +31,14 @@ import CoreData /** A storage interface that is backed only by memory. */ -public class InMemoryStore: StorageInterface, DefaultInitializableStore { +public final class InMemoryStore: StorageInterface, DefaultInitializableStore { /** Initializes an `InMemoryStore` for the specified configuration - parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. */ - public required init(configuration: String?) { + public init(configuration: String?) { self.configuration = configuration } @@ -49,7 +49,7 @@ public class InMemoryStore: StorageInterface, DefaultInitializableStore { /** Initializes an `InMemoryStore` with the "Default" configuration */ - public required init() { + public init() { self.configuration = nil } diff --git a/Sources/Setting Up/StorageInterfaces/LegacySQLiteStore.swift b/Sources/Setting Up/StorageInterfaces/LegacySQLiteStore.swift index 1991efc..5b8a296 100644 --- a/Sources/Setting Up/StorageInterfaces/LegacySQLiteStore.swift +++ b/Sources/Setting Up/StorageInterfaces/LegacySQLiteStore.swift @@ -32,7 +32,7 @@ import Foundation A storage interface backed by an SQLite database that was created before CoreStore 2.0.0. - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `LegacySQLiteStore` instead of `SQLiteStore`. */ -public final class LegacySQLiteStore: SQLiteStore { +public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore { /** Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `DataStack`'s `addStorage()` methods, a new SQLite file will be created if it does not exist. @@ -42,14 +42,12 @@ public final class LegacySQLiteStore: SQLiteStore { - parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration. - parameter localStorageOptions: When the `SQLiteStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`. */ - public required init(fileURL: NSURL, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), localStorageOptions: LocalStorageOptions = nil) { + public init(fileURL: NSURL, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), localStorageOptions: LocalStorageOptions = nil) { - super.init( - fileURL: fileURL, - configuration: configuration, - mappingModelBundles: mappingModelBundles, - localStorageOptions: localStorageOptions - ) + self.fileURL = fileURL + self.configuration = configuration + self.mappingModelBundles = mappingModelBundles + self.localStorageOptions = localStorageOptions } /** @@ -61,23 +59,97 @@ public final class LegacySQLiteStore: SQLiteStore { - parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration. - parameter localStorageOptions: When the `SQLiteStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`. */ - public required init(fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), localStorageOptions: LocalStorageOptions = nil) { + public init(fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), localStorageOptions: LocalStorageOptions = nil) { - super.init( - fileURL: LegacySQLiteStore.defaultRootDirectory.URLByAppendingPathComponent( - fileName, - isDirectory: false - ), - configuration: configuration, - mappingModelBundles: mappingModelBundles, - localStorageOptions: localStorageOptions + self.fileURL = LegacySQLiteStore.defaultRootDirectory.URLByAppendingPathComponent( + fileName, + isDirectory: false ) + self.configuration = configuration + self.mappingModelBundles = mappingModelBundles + self.localStorageOptions = localStorageOptions } - // MARK: SQLiteStore + // MARK: DefaultInitializableStore - internal override class var defaultRootDirectory: NSURL { + /** + Initializes an `LegacySQLiteStore` with an all-default settings: a `fileURL` pointing to a ".sqlite" file in the "Application Support" directory (or the "Caches" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `.AllowProgresiveMigration`. + - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `LegacySQLiteStore` instead of `SQLiteStore`. + */ + public init() { + + self.fileURL = LegacySQLiteStore.defaultFileURL + self.configuration = nil + self.mappingModelBundles = NSBundle.allBundles() + self.localStorageOptions = nil + } + + + // MAKR: LocalStorage + + /** + The `NSURL` that points to the SQLite file + */ + public let fileURL: NSURL + + /** + The `NSBundle`s from which to search mapping models for migrations + */ + public let mappingModelBundles: [NSBundle] + + /** + Options that tell the `DataStack` how to setup the persistent store + */ + public var localStorageOptions: LocalStorageOptions + + + // MARK: StorageInterface + + /** + The string identifier for the `NSPersistentStore`'s `type` property. For `SQLiteStore`s, this is always set to `NSSQLiteStoreType`. + */ + public static let storeType = NSSQLiteStoreType + + /** + The configuration name in the model file + */ + public let configuration: String? + + /** + The options dictionary for the `NSPersistentStore`. For `SQLiteStore`s, this is always set to + ``` + [NSSQLitePragmasOption: ["journal_mode": "WAL"]] + ``` + */ + public let storeOptions: [String: AnyObject]? = [NSSQLitePragmasOption: ["journal_mode": "WAL"]] + + /** + Called by the `DataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. For `SQLiteStore`, this converts the database's WAL journaling mode to DELETE before deleting the file. + */ + public func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel) throws { + + // TODO: check if attached to persistent store + + let fileURL = self.fileURL + try autoreleasepool { + + let journalUpdatingCoordinator = NSPersistentStoreCoordinator(managedObjectModel: soureModel) + let store = try journalUpdatingCoordinator.addPersistentStoreWithType( + self.dynamicType.storeType, + configuration: self.configuration, + URL: fileURL, + options: [NSSQLitePragmasOption: ["journal_mode": "DELETE"]] + ) + try journalUpdatingCoordinator.removePersistentStore(store) + try NSFileManager.defaultManager().removeItemAtURL(fileURL) + } + } + + + // MARK: Internal + + internal static let defaultRootDirectory: NSURL = { #if os(tvOS) let systemDirectorySearchPath = NSSearchPathDirectory.CachesDirectory @@ -89,24 +161,9 @@ public final class LegacySQLiteStore: SQLiteStore { systemDirectorySearchPath, inDomains: .UserDomainMask ).first! - } + }() - internal override class var defaultFileURL: NSURL { - - return LegacySQLiteStore.defaultRootDirectory - .URLByAppendingPathComponent(DataStack.applicationName, isDirectory: false) - .URLByAppendingPathExtension("sqlite") - } - - - // MARK: DefaultInitializableStore - - /** - Initializes an `LegacySQLiteStore` with an all-default settings: a `fileURL` pointing to a ".sqlite" file in the "Application Support" directory (or the "Caches" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `.AllowProgresiveMigration`. - - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `LegacySQLiteStore` instead of `SQLiteStore`. - */ - public required init() { - - super.init(fileURL: LegacySQLiteStore.defaultFileURL) - } + internal static let defaultFileURL = LegacySQLiteStore.defaultRootDirectory + .URLByAppendingPathComponent(DataStack.applicationName, isDirectory: false) + .URLByAppendingPathExtension("sqlite") } diff --git a/Sources/Setting Up/StorageInterfaces/LocalStorageOptions.swift b/Sources/Setting Up/StorageInterfaces/LocalStorageOptions.swift deleted file mode 100644 index 9a28cf3..0000000 --- a/Sources/Setting Up/StorageInterfaces/LocalStorageOptions.swift +++ /dev/null @@ -1,74 +0,0 @@ -// -// LocalStorageOptions.swift -// CoreStore -// -// Copyright © 2016 John Rommel Estropia -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - - -// MARK: - LocalStorageOptions - -/** - The `LocalStorageOptions` provides settings that tells the `DataStack` how to setup the persistent store for `LocalStorage` implementers. - */ -public struct LocalStorageOptions: OptionSetType, NilLiteralConvertible { - - /** - Tells the `DataStack` that the store should not be migrated or recreated, and should simply fail on model mismatch - */ - public static let None = LocalStorageOptions(rawValue: 0) - - /** - Tells the `DataStack` to delete and recreate the store on model mismatch, otherwise exceptions will be thrown on failure instead - */ - public static let RecreateStoreOnModelMismatch = LocalStorageOptions(rawValue: 1 << 0) - - /** - Tells the `DataStack` to prevent progressive migrations for the store - */ - public static let PreventProgressiveMigration = LocalStorageOptions(rawValue: 1 << 1) - - /** - Tells the `DataStack` to allow lightweight migration for the store when added synchronously - */ - public static let AllowSynchronousLightweightMigration = LocalStorageOptions(rawValue: 1 << 2) - - - // MARK: OptionSetType - - public init(rawValue: Int) { - - self.rawValue = rawValue - } - - - // MARK: RawRepresentable - - public let rawValue: Int - - - // MARK: NilLiteralConvertible - - public init(nilLiteral: ()) { - - self.rawValue = 0 - } -} diff --git a/Sources/Setting Up/StorageInterfaces/SQLiteStore.swift b/Sources/Setting Up/StorageInterfaces/SQLiteStore.swift index 89b7006..8f8ddbf 100644 --- a/Sources/Setting Up/StorageInterfaces/SQLiteStore.swift +++ b/Sources/Setting Up/StorageInterfaces/SQLiteStore.swift @@ -32,7 +32,7 @@ import CoreData A storage interface that is backed by an SQLite database. - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `LegacySQLiteStore` instead of `SQLiteStore`. */ -public class SQLiteStore: LocalStorage, DefaultInitializableStore { +public final class SQLiteStore: LocalStorage, DefaultInitializableStore { /** Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `DataStack`'s `addStorage()` methods, a new SQLite file will be created if it does not exist. @@ -42,7 +42,7 @@ public class SQLiteStore: LocalStorage, DefaultInitializableStore { - parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration. - parameter localStorageOptions: When the `SQLiteStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`. */ - public required init(fileURL: NSURL, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), localStorageOptions: LocalStorageOptions = nil) { + public init(fileURL: NSURL, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), localStorageOptions: LocalStorageOptions = nil) { self.fileURL = fileURL self.configuration = configuration @@ -59,7 +59,7 @@ public class SQLiteStore: LocalStorage, DefaultInitializableStore { - parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration - parameter localStorageOptions: When the `SQLiteStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`. */ - public required init(fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), localStorageOptions: LocalStorageOptions = nil) { + public init(fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), localStorageOptions: LocalStorageOptions = nil) { self.fileURL = SQLiteStore.defaultRootDirectory .URLByAppendingPathComponent(fileName, isDirectory: false) @@ -75,7 +75,7 @@ public class SQLiteStore: LocalStorage, DefaultInitializableStore { Initializes an `SQLiteStore` with an all-default settings: a `fileURL` pointing to a ".sqlite" file in the "Application Support/" directory (or the "Caches/" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `.AllowProgresiveMigration`. - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `LegacySQLiteStore` instead of `SQLiteStore`. */ - public required init() { + public init() { self.fileURL = SQLiteStore.defaultFileURL self.configuration = nil @@ -145,9 +145,9 @@ public class SQLiteStore: LocalStorage, DefaultInitializableStore { } - // MARK: Internal + // MARK: Private - internal class var defaultRootDirectory: NSURL { + internal static let defaultRootDirectory: NSURL = { #if os(tvOS) let systemDirectorySearchPath = NSSearchPathDirectory.CachesDirectory @@ -163,14 +163,12 @@ public class SQLiteStore: LocalStorage, DefaultInitializableStore { NSBundle.mainBundle().bundleIdentifier ?? "com.CoreStore.DataStack", isDirectory: true ) - } + }() - internal class var defaultFileURL: NSURL { - - let applicationName = (NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as? String) ?? "CoreData" - - return SQLiteStore.defaultRootDirectory - .URLByAppendingPathComponent(applicationName, isDirectory: false) - .URLByAppendingPathExtension("sqlite") - } + internal static let defaultFileURL = SQLiteStore.defaultRootDirectory + .URLByAppendingPathComponent( + (NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as? String) ?? "CoreData", + isDirectory: false + ) + .URLByAppendingPathExtension("sqlite") } diff --git a/Sources/Setting Up/StorageInterfaces/StorageInterface.swift b/Sources/Setting Up/StorageInterfaces/StorageInterface.swift index f45fa8e..6d64126 100644 --- a/Sources/Setting Up/StorageInterfaces/StorageInterface.swift +++ b/Sources/Setting Up/StorageInterfaces/StorageInterface.swift @@ -64,6 +64,56 @@ public protocol DefaultInitializableStore: StorageInterface { } +// MARK: - LocalStorageOptions + +/** + The `LocalStorageOptions` provides settings that tells the `DataStack` how to setup the persistent store for `LocalStorage` implementers. + */ +public struct LocalStorageOptions: OptionSetType, NilLiteralConvertible { + + /** + Tells the `DataStack` that the store should not be migrated or recreated, and should simply fail on model mismatch + */ + public static let None = LocalStorageOptions(rawValue: 0) + + /** + Tells the `DataStack` to delete and recreate the store on model mismatch, otherwise exceptions will be thrown on failure instead + */ + public static let RecreateStoreOnModelMismatch = LocalStorageOptions(rawValue: 1 << 0) + + /** + Tells the `DataStack` to prevent progressive migrations for the store + */ + public static let PreventProgressiveMigration = LocalStorageOptions(rawValue: 1 << 1) + + /** + Tells the `DataStack` to allow lightweight migration for the store when added synchronously + */ + public static let AllowSynchronousLightweightMigration = LocalStorageOptions(rawValue: 1 << 2) + + + // MARK: OptionSetType + + public init(rawValue: Int) { + + self.rawValue = rawValue + } + + + // MARK: RawRepresentable + + public let rawValue: Int + + + // MARK: NilLiteralConvertible + + public init(nilLiteral: ()) { + + self.rawValue = 0 + } +} + + // MARK: - LocalStorage /**