Compare commits

..

18 Commits

Author SHA1 Message Date
John Estropia
981b560d53 test travis ci 2017-05-30 11:14:57 +09:00
John Estropia
c4c4dd55cd test travis build 2017-05-30 11:06:30 +09:00
John Rommel Estropia
1ddbe20c86 Updated README, fixed demo app, and bumped to 4.0.1 2017-05-28 11:37:40 +09:00
John Rommel Estropia
da9e8c1550 disallow "empty" default values on some ImportableAttributeTypes 2017-05-28 10:50:25 +09:00
John Estropia
ef0937fec4 make unit tests happy 2017-05-24 12:15:55 +09:00
John Estropia
35885b40de README done! Welcome to CoreStore 4.0! 2017-05-24 12:05:34 +09:00
John Rommel Estropia
d669569196 WIP: readme 2017-05-24 00:37:32 +09:00
John Rommel Estropia
ae919ff3c8 WIP: readme 2017-05-24 00:35:25 +09:00
John Rommel Estropia
1a7a4690d1 WIP: readme 2017-05-24 00:33:43 +09:00
John Rommel Estropia
b9b96d1a35 WIP: Updating README and other docs. Some minor fixes 2017-05-22 01:27:38 +09:00
John Rommel Estropia
da3a9590ac accept optionals in setValue 2017-05-21 09:38:56 +09:00
John Rommel Estropia
6b3d75bea1 fix fixits 2017-05-21 09:29:34 +09:00
John Rommel Estropia
d44721fef0 fix xcode hints 2017-05-21 09:11:34 +09:00
John Rommel Estropia
3f268e8376 added NSManagedObject.setValue(_:forKvcKey:willSetValue:didSetValue:) 2017-05-21 09:06:29 +09:00
John Rommel Estropia
303fea4ebe fix warnings 2017-05-21 08:51:38 +09:00
John Estropia
77173cdad0 minor fix 2017-05-18 21:10:43 +09:00
John Estropia
1e24a7d739 ListObserver's listMonitorDidChange(_:) and listMonitorDidRefetch(_:) handlers are now required. 2017-05-18 12:59:58 +09:00
John Estropia
a3b33bedb8 added more migration error types 2017-05-18 12:59:02 +09:00
33 changed files with 1042 additions and 617 deletions

View File

@@ -9,7 +9,7 @@ env:
global: global:
- LC_CTYPE=en_US.UTF-8 - LC_CTYPE=en_US.UTF-8
- LANG=en_US.UTF-8 - LANG=en_US.UTF-8
matrix: matrix:
- DESTINATION="OS=10.3,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO" - DESTINATION="OS=10.3,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO" - DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO" - DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
@@ -25,7 +25,7 @@ matrix:
before_install: before_install:
- gem install cocoapods --no-rdoc --no-ri --no-document --quiet - gem install cocoapods --no-rdoc --no-ri --no-document --quiet
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
- curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.20.1/Carthage.pkg" - curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.23.0/Carthage.pkg"
- sudo installer -pkg "Carthage.pkg" -target / - sudo installer -pkg "Carthage.pkg" -target /
- rm "Carthage.pkg" - rm "Carthage.pkg"
before_script: before_script:

View File

@@ -1,6 +1,6 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = "CoreStore" s.name = "CoreStore"
s.version = "4.0.0-beta3" s.version = "4.0.1"
s.license = "MIT" s.license = "MIT"
s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift" s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift"
s.homepage = "https://github.com/JohnEstropia/CoreStore" s.homepage = "https://github.com/JohnEstropia/CoreStore"

View File

@@ -214,10 +214,10 @@
B52F743E1E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; }; B52F743E1E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; };
B52F743F1E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; }; B52F743F1E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; };
B52F74401E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; }; B52F74401E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; };
B52F74411E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */; }; B52F74411E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */; };
B52F74421E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */; }; B52F74421E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */; };
B52F74431E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */; }; B52F74431E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */; };
B52F74441E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */; }; B52F74441E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */; };
B52F74451E9B8724005F3DAC /* XcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */; }; B52F74451E9B8724005F3DAC /* XcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */; };
B52F74461E9B8724005F3DAC /* XcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */; }; B52F74461E9B8724005F3DAC /* XcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */; };
B52F74471E9B8724005F3DAC /* XcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */; }; B52F74471E9B8724005F3DAC /* XcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */; };
@@ -426,10 +426,10 @@
B56923FB1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */; }; B56923FB1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */; };
B56923FC1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */; }; B56923FC1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */; };
B56923FD1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */; }; B56923FD1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */; };
B56923FF1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */; }; B56923FF1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */; };
B56924001EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */; }; B56924001EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */; };
B56924011EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */; }; B56924011EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */; };
B56924021EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */; }; B56924021EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */; };
B56964D41B22FFAD0075EE4A /* DataStack+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */; }; B56964D41B22FFAD0075EE4A /* DataStack+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */; };
B56965241B356B820075EE4A /* MigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965231B356B820075EE4A /* MigrationResult.swift */; }; B56965241B356B820075EE4A /* MigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965231B356B820075EE4A /* MigrationResult.swift */; };
B57D27BE1D0BBE8200539C58 /* BaseTestDataTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B57D27BD1D0BBE8200539C58 /* BaseTestDataTestCase.swift */; }; B57D27BE1D0BBE8200539C58 /* BaseTestDataTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B57D27BD1D0BBE8200539C58 /* BaseTestDataTestCase.swift */; };
@@ -746,7 +746,7 @@
B52DD17D1BE1F8CC00949AFE /* CoreStoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreStoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; B52DD17D1BE1F8CC00949AFE /* CoreStoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreStoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaHistory.swift; sourceTree = "<group>"; }; B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaHistory.swift; sourceTree = "<group>"; };
B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicSchema.swift; sourceTree = "<group>"; }; B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicSchema.swift; sourceTree = "<group>"; };
B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyXcodeDataModelSchema.swift; sourceTree = "<group>"; }; B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnsafeDataModelSchema.swift; sourceTree = "<group>"; };
B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XcodeDataModelSchema.swift; sourceTree = "<group>"; }; B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XcodeDataModelSchema.swift; sourceTree = "<group>"; };
B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreSchema.swift; sourceTree = "<group>"; }; B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreSchema.swift; sourceTree = "<group>"; };
B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Logging.swift"; sourceTree = "<group>"; }; B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Logging.swift"; sourceTree = "<group>"; };
@@ -800,7 +800,7 @@
B56923DF1EB827F5007C4DC9 /* XcodeSchemaMappingProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XcodeSchemaMappingProvider.swift; sourceTree = "<group>"; }; B56923DF1EB827F5007C4DC9 /* XcodeSchemaMappingProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XcodeSchemaMappingProvider.swift; sourceTree = "<group>"; };
B56923F41EB828BF007C4DC9 /* CSDynamicSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSDynamicSchema.swift; sourceTree = "<group>"; }; B56923F41EB828BF007C4DC9 /* CSDynamicSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSDynamicSchema.swift; sourceTree = "<group>"; };
B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSXcodeDataModelSchema.swift; sourceTree = "<group>"; }; B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSXcodeDataModelSchema.swift; sourceTree = "<group>"; };
B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSLegacyXcodeDataModelSchema.swift; sourceTree = "<group>"; }; B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSUnsafeDataModelSchema.swift; sourceTree = "<group>"; };
B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = "DataStack+Migration.swift"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = "DataStack+Migration.swift"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
B56965231B356B820075EE4A /* MigrationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationResult.swift; sourceTree = "<group>"; }; B56965231B356B820075EE4A /* MigrationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationResult.swift; sourceTree = "<group>"; };
B57D27BD1D0BBE8200539C58 /* BaseTestDataTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTestDataTestCase.swift; sourceTree = "<group>"; }; B57D27BD1D0BBE8200539C58 /* BaseTestDataTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTestDataTestCase.swift; sourceTree = "<group>"; };
@@ -1108,7 +1108,7 @@
B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */, B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */,
B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */, B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */,
B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */, B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */,
B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */, B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */,
); );
name = "Dynamic Schema"; name = "Dynamic Schema";
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1190,7 +1190,7 @@
children = ( children = (
B56923F41EB828BF007C4DC9 /* CSDynamicSchema.swift */, B56923F41EB828BF007C4DC9 /* CSDynamicSchema.swift */,
B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */, B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */,
B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */, B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */,
); );
name = "Dynamic Schema"; name = "Dynamic Schema";
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1788,7 +1788,7 @@
B5E1B5981CAA0C23007FD580 /* CSObjectObserver.swift in Sources */, B5E1B5981CAA0C23007FD580 /* CSObjectObserver.swift in Sources */,
B5519A5F1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */, B5519A5F1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
B52FD3AA1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */, B52FD3AA1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74411E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */, B52F74411E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */,
B51FE5AB1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */, B51FE5AB1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
B5A9921F1EA898710091A2E3 /* UserInfo.swift in Sources */, B5A9921F1EA898710091A2E3 /* UserInfo.swift in Sources */,
B54A6A551BA15F2A007870FD /* FetchedResultsControllerDelegate.swift in Sources */, B54A6A551BA15F2A007870FD /* FetchedResultsControllerDelegate.swift in Sources */,
@@ -1900,7 +1900,7 @@
B5A991EC1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */, B5A991EC1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
B5FE4DA71C84FB4400FA6A91 /* InMemoryStore.swift in Sources */, B5FE4DA71C84FB4400FA6A91 /* InMemoryStore.swift in Sources */,
B52F743D1E9B8724005F3DAC /* DynamicSchema.swift in Sources */, B52F743D1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
B56923FF1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */, B56923FF1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
B5ECDBEC1CA6BF2000C7F112 /* CSFrom.swift in Sources */, B5ECDBEC1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
B56923EC1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */, B56923EC1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
B5E834B91B76311F001D3D50 /* BaseDataTransaction+Importing.swift in Sources */, B5E834B91B76311F001D3D50 /* BaseDataTransaction+Importing.swift in Sources */,
@@ -1972,7 +1972,7 @@
B5E1B59A1CAA0C23007FD580 /* CSObjectObserver.swift in Sources */, B5E1B59A1CAA0C23007FD580 /* CSObjectObserver.swift in Sources */,
B5519A601CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */, B5519A601CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
B52FD3AB1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */, B52FD3AB1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74421E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */, B52F74421E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */,
B51FE5AD1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */, B51FE5AD1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
B5A992201EA898720091A2E3 /* UserInfo.swift in Sources */, B5A992201EA898720091A2E3 /* UserInfo.swift in Sources */,
B5FE4DAD1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */, B5FE4DAD1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */,
@@ -2084,7 +2084,7 @@
B5A991ED1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */, B5A991ED1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
B5ECDBEE1CA6BF2000C7F112 /* CSFrom.swift in Sources */, B5ECDBEE1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
B52F743E1E9B8724005F3DAC /* DynamicSchema.swift in Sources */, B52F743E1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
B56924001EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */, B56924001EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */, 82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */,
B56923ED1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */, B56923ED1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
82BA18B91C4BBD4A00A0916E /* From.swift in Sources */, 82BA18B91C4BBD4A00A0916E /* From.swift in Sources */,
@@ -2156,7 +2156,7 @@
B5ECDC211CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */, B5ECDC211CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */,
B52DD1C21BE1F94600949AFE /* MigrationManager.swift in Sources */, B52DD1C21BE1F94600949AFE /* MigrationManager.swift in Sources */,
B52FD3AD1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */, B52FD3AD1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74441E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */, B52F74441E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */,
B5ECDC2D1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */, B5ECDC2D1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */,
B5A992221EA898720091A2E3 /* UserInfo.swift in Sources */, B5A992221EA898720091A2E3 /* UserInfo.swift in Sources */,
B5D7A5BA1CA3BF8F005C752B /* CSInto.swift in Sources */, B5D7A5BA1CA3BF8F005C752B /* CSInto.swift in Sources */,
@@ -2268,7 +2268,7 @@
B5A991EF1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */, B5A991EF1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
B5220E201D130813009BC71E /* CSObjectMonitor.swift in Sources */, B5220E201D130813009BC71E /* CSObjectMonitor.swift in Sources */,
B52F74401E9B8724005F3DAC /* DynamicSchema.swift in Sources */, B52F74401E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
B56924021EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */, B56924021EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
B5220E171D1306DF009BC71E /* UnsafeDataTransaction+Observing.swift in Sources */, B5220E171D1306DF009BC71E /* UnsafeDataTransaction+Observing.swift in Sources */,
B56923EF1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */, B56923EF1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
B53FBA081CAB300C00F0D40A /* CSMigrationType.swift in Sources */, B53FBA081CAB300C00F0D40A /* CSMigrationType.swift in Sources */,
@@ -2340,7 +2340,7 @@
B5519A611CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */, B5519A611CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
B5FE4DAE1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */, B5FE4DAE1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */,
B52FD3AC1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */, B52FD3AC1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74431E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */, B52F74431E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */,
B51FE5AE1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */, B51FE5AE1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
B5A992211EA898720091A2E3 /* UserInfo.swift in Sources */, B5A992211EA898720091A2E3 /* UserInfo.swift in Sources */,
B563218C1BD65216006C9394 /* DataStack+Transaction.swift in Sources */, B563218C1BD65216006C9394 /* DataStack+Transaction.swift in Sources */,
@@ -2452,7 +2452,7 @@
B5A991EE1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */, B5A991EE1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
B5ECDBEF1CA6BF2000C7F112 /* CSFrom.swift in Sources */, B5ECDBEF1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
B52F743F1E9B8724005F3DAC /* DynamicSchema.swift in Sources */, B52F743F1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
B56924011EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */, B56924011EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */, B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */,
B56923EE1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */, B56923EE1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
B56321861BD65216006C9394 /* CoreStoreLogger.swift in Sources */, B56321861BD65216006C9394 /* CoreStoreLogger.swift in Sources */,

View File

@@ -8,7 +8,6 @@
import UIKit import UIKit
import CoreStore
// MARK: - AppDelegate // MARK: - AppDelegate

View File

@@ -17,11 +17,11 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0.1</string> <string>4.0.1</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>4</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>

View File

@@ -91,6 +91,11 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
} }
} }
func listMonitorDidRefetch(_ monitor: ListMonitor<NSManagedObject>) {
self.listMonitorDidChange(monitor)
}
// MARK: UITableViewDataSource // MARK: UITableViewDataSource
@objc dynamic func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { @objc dynamic func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
@@ -148,7 +153,10 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
label: "Model V1", label: "Model V1",
entityType: OrganismV1.self, entityType: OrganismV1.self,
schemaHistory: SchemaHistory( schemaHistory: SchemaHistory(
modelName: "MigrationDemo", XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
),
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"] migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
) )
), ),
@@ -156,7 +164,13 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
label: "Model V2", label: "Model V2",
entityType: OrganismV2.self, entityType: OrganismV2.self,
schemaHistory: SchemaHistory( schemaHistory: SchemaHistory(
modelName: "MigrationDemo", XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: [
"MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
]
),
migrationChain: [ migrationChain: [
"MigrationDemo": "MigrationDemoV2", "MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2" "MigrationDemoV3": "MigrationDemoV2"
@@ -167,7 +181,10 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
label: "Model V3", label: "Model V3",
entityType: OrganismV3.self, entityType: OrganismV3.self,
schemaHistory: SchemaHistory( schemaHistory: SchemaHistory(
modelName: "MigrationDemo", XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
),
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"] migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
) )
) )

View File

@@ -40,7 +40,7 @@ class BaseTestCase: XCTestCase {
func prepareStack<T>(configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> T) -> T { func prepareStack<T>(configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> T) -> T {
let stack = DataStack( let stack = DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: Bundle(for: type(of: self)) bundle: Bundle(for: type(of: self))
) )
do { do {

View File

@@ -163,7 +163,7 @@
- (void)test_ThatDataStacks_BridgeCorrectly { - (void)test_ThatDataStacks_BridgeCorrectly {
CSDataStack *dataStack = [[CSDataStack alloc] CSDataStack *dataStack = [[CSDataStack alloc]
initWithModelName:@"Model" initWithXcodeModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]] bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil]; versionChain:nil];
XCTAssertNotNil(dataStack); XCTAssertNotNil(dataStack);
@@ -201,7 +201,7 @@
[CSCoreStore [CSCoreStore
setDefaultStack:[[CSDataStack alloc] setDefaultStack:[[CSDataStack alloc]
initWithModelName:@"Model" initWithXcodeModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]] bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil]]; versionChain:nil]];
[CSCoreStore [CSCoreStore
@@ -253,37 +253,5 @@
} }
[self waitForExpectationsWithTimeout:10 handler:nil]; [self waitForExpectationsWithTimeout:10 handler:nil];
} }
#if TARGET_OS_IOS || TARGET_OS_WATCHOS || TARGET_OS_TV
- (void)test_ThatDataStacks_CanCreateCustomFetchedResultsControllers {
[CSCoreStore
setDefaultStack:[[CSDataStack alloc]
initWithModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil]];
[CSCoreStore
addInMemoryStorageAndWait:[CSInMemoryStore new]
error:nil];
NSFetchedResultsController *controller =
[[CSCoreStore defaultStack]
createFetchedResultsControllerFrom:CSFromClass([TestEntity1 class])
sectionBy:[CSSectionBy keyPath:CSKeyPath(TestEntity1, testString)]
fetchClauses:@[CSWhereFormat(@"%K > %d", CSKeyPath(TestEntity1, testEntityID), 100),
CSOrderByKeys(CSSortAscending(CSKeyPath(TestEntity1, testString)), nil),
CSTweakRequest(^(NSFetchRequest *fetchRequest) { fetchRequest.fetchLimit = 10; })]];
XCTAssertNotNil(controller);
XCTAssertEqualObjects(controller.fetchRequest.entity.managedObjectClassName, [[TestEntity1 class] description]);
XCTAssertEqualObjects(controller.sectionNameKeyPath, CSKeyPath(TestEntity1, testString));
XCTAssertEqualObjects(controller.fetchRequest.predicate,
CSWhereFormat(@"%K > %d", CSKeyPath(TestEntity1, testEntityID), 100).predicate);
XCTAssertEqualObjects(controller.fetchRequest.sortDescriptors,
CSOrderByKeys(CSSortAscending(CSKeyPath(TestEntity1, testString)), nil).sortDescriptors);
XCTAssertEqual(controller.fetchRequest.fetchLimit, 10);
}
#endif
@end @end

View File

@@ -28,12 +28,18 @@ import XCTest
@testable @testable
import CoreStore import CoreStore
#if os(OSX)
typealias Color = NSColor
#else
typealias Color = UIColor
#endif
class Animal: CoreStoreObject { class Animal: CoreStoreObject {
let species = Value.Required<String>("species", default: "Swift") let species = Value.Required<String>("species", default: "Swift")
let master = Relationship.ToOne<Person>("master") let master = Relationship.ToOne<Person>("master")
let color = Transformable.Optional<UIColor>("color") let color = Transformable.Optional<Color>("color")
} }
class Dog: Animal { class Dog: Animal {
@@ -102,7 +108,7 @@ class DynamicModelTests: BaseTestDataTestCase {
XCTAssertEqual(animal.species.value, "Sparrow") XCTAssertEqual(animal.species.value, "Sparrow")
animal.color .= .yellow animal.color .= .yellow
XCTAssertEqual(animal.color.value, UIColor.yellow) XCTAssertEqual(animal.color.value, Color.yellow)
let dog = transaction.create(Into<Dog>()) let dog = transaction.create(Into<Dog>())
XCTAssertEqual(dog.species.value, "Swift") XCTAssertEqual(dog.species.value, "Swift")
@@ -168,7 +174,6 @@ class DynamicModelTests: BaseTestDataTestCase {
success: { success: {
fetchDone.fulfill() fetchDone.fulfill()
withExtendedLifetime(stack, {})
}, },
failure: { _ in failure: { _ in

View File

@@ -67,7 +67,7 @@ class SetupTests: BaseTestDataTestCase {
let stack = self.expectLogger([.logWarning]) { let stack = self.expectLogger([.logWarning]) {
DataStack( DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: Bundle(for: type(of: self)), bundle: Bundle(for: type(of: self)),
migrationChain: migrationChain migrationChain: migrationChain
) )
@@ -84,7 +84,7 @@ class SetupTests: BaseTestDataTestCase {
dynamic func test_ThatInMemoryStores_SetupCorrectly() { dynamic func test_ThatInMemoryStores_SetupCorrectly() {
let stack = DataStack( let stack = DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: Bundle(for: type(of: self)) bundle: Bundle(for: type(of: self))
) )
do { do {
@@ -139,7 +139,7 @@ class SetupTests: BaseTestDataTestCase {
dynamic func test_ThatSQLiteStores_SetupCorrectly() { dynamic func test_ThatSQLiteStores_SetupCorrectly() {
let stack = DataStack( let stack = DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: Bundle(for: type(of: self)) bundle: Bundle(for: type(of: self))
) )
do { do {
@@ -207,7 +207,7 @@ class SetupTests: BaseTestDataTestCase {
do { do {
let stack = DataStack( let stack = DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: Bundle(for: type(of: self)) bundle: Bundle(for: type(of: self))
) )
try! stack.addStorageAndWait(sqliteStore) try! stack.addStorageAndWait(sqliteStore)
@@ -226,7 +226,7 @@ class SetupTests: BaseTestDataTestCase {
let metadata = try createStore() let metadata = try createStore()
let stack = DataStack( let stack = DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: Bundle(for: type(of: self)) bundle: Bundle(for: type(of: self))
) )
try sqliteStore.cs_eraseStorageAndWait( try sqliteStore.cs_eraseStorageAndWait(
@@ -259,7 +259,7 @@ class SetupTests: BaseTestDataTestCase {
dynamic func test_ThatLegacySQLiteStores_SetupCorrectly() { dynamic func test_ThatLegacySQLiteStores_SetupCorrectly() {
let stack = DataStack( let stack = DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: Bundle(for: type(of: self)) bundle: Bundle(for: type(of: self))
) )
do { do {
@@ -327,7 +327,7 @@ class SetupTests: BaseTestDataTestCase {
do { do {
let stack = DataStack( let stack = DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: Bundle(for: type(of: self)) bundle: Bundle(for: type(of: self))
) )
try! stack.addStorageAndWait(sqliteStore) try! stack.addStorageAndWait(sqliteStore)
@@ -346,7 +346,7 @@ class SetupTests: BaseTestDataTestCase {
let metadata = try createStore() let metadata = try createStore()
let stack = DataStack( let stack = DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: Bundle(for: type(of: self)) bundle: Bundle(for: type(of: self))
) )
try sqliteStore.cs_eraseStorageAndWait( try sqliteStore.cs_eraseStorageAndWait(

890
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -49,41 +49,22 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
/** /**
Initializes a `CSDataStack` from the model with the specified `modelName` in the specified `bundle`. Initializes a `CSDataStack` from the model with the specified `modelName` in the specified `bundle`.
- parameter modelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set. - parameter xcodeModelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set.
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used. - parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
- 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. - 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 @objc
public convenience init(modelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) { public convenience init(xcodeModelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
self.init( self.init(
DataStack( DataStack(
modelName: modelName ?? DataStack.applicationName, xcodeModelName: xcodeModelName ?? DataStack.applicationName,
bundle: bundle ?? Bundle.main, bundle: bundle ?? Bundle.main,
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
) )
) )
} }
/**
Initializes a `CSDataStack` from the model with the specified `modelName` in the specified `bundle`.
- parameter modelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set.
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
- 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: XcodeDataModelFileName?, bundle: Bundle?, versionTree: [String: String]?) {
self.init(
DataStack(
modelName: modelName ?? DataStack.applicationName,
bundle: bundle ?? Bundle.main,
migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
)
)
}
/** /**
Returns the stack's model version. The version string is the same as the name of the version-specific .xcdatamodeld file. Returns the stack's model version. The version string is the same as the name of the version-specific .xcdatamodeld file.
*/ */
@@ -227,6 +208,19 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
// MARK: Deprecated // MARK: Deprecated
@available(*, deprecated, message: "Use the -[initWithXcodeModelName:bundle:versionChain:] initializer.")
@objc
public convenience init(modelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
self.init(
DataStack(
xcodeModelName: modelName ?? DataStack.applicationName,
bundle: bundle ?? Bundle.main,
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
)
)
}
@available(*, deprecated, message: "Use the -[initWithModelName:bundle:versionChain:] initializer.") @available(*, deprecated, message: "Use the -[initWithModelName:bundle:versionChain:] initializer.")
@objc @objc
public convenience init(model: NSManagedObjectModel, versionChain: [String]?) { public convenience init(model: NSManagedObjectModel, versionChain: [String]?) {

View File

@@ -78,7 +78,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
} }
/** /**
Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `[CSLocalStorageOptions none]`. Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, and `localStorageOptions` set to `[CSLocalStorageOptions none]`.
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property. - Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
*/ */

View File

@@ -1,5 +1,5 @@
// //
// CSLegacyXcodeDataModelSchema.swift // CSUnsafeDataModelSchema.swift
// CoreStore // CoreStore
// //
// Copyright © 2017 John Rommel Estropia // Copyright © 2017 John Rommel Estropia
@@ -27,18 +27,18 @@ import CoreData
import Foundation import Foundation
// MARK: - CSLegacyXcodeDataModelSchema // MARK: - CSUnsafeDataModelSchema
/** /**
The `CSLegacyXcodeDataModelSchema` serves as the Objective-C bridging type for `LegacyXcodeDataModelSchema`. The `CSUnsafeDataModelSchema` serves as the Objective-C bridging type for `UnsafeDataModelSchema`.
- SeeAlso: `LegacyXcodeDataModelSchema` - SeeAlso: `UnsafeDataModelSchema`
*/ */
@objc @objc
public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType { public final class CSUnsafeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType {
/** /**
Initializes a `CSLegacyXcodeDataModelSchema` from an `NSManagedObjectModel`. Initializes a `CSUnsafeDataModelSchema` from an `NSManagedObjectModel`.
- parameter modelName: the model version, typically the file name of an *.xcdatamodeld file (without the file extension) - parameter modelName: the model version, typically the file name of an *.xcdatamodeld file (without the file extension)
- parameter model: the `NSManagedObjectModel` - parameter model: the `NSManagedObjectModel`
@@ -46,7 +46,7 @@ public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, Core
@objc @objc
public required init(modelName: ModelVersion, model: NSManagedObjectModel) { public required init(modelName: ModelVersion, model: NSManagedObjectModel) {
self.bridgeToSwift = LegacyXcodeDataModelSchema( self.bridgeToSwift = UnsafeDataModelSchema(
modelName: modelName, modelName: modelName,
model: model model: model
) )
@@ -62,7 +62,7 @@ public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, Core
public override func isEqual(_ object: Any?) -> Bool { public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSLegacyXcodeDataModelSchema else { guard let object = object as? CSUnsafeDataModelSchema else {
return false return false
} }
@@ -92,9 +92,9 @@ public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, Core
// MARK: CoreStoreObjectiveCType // MARK: CoreStoreObjectiveCType
public let bridgeToSwift: LegacyXcodeDataModelSchema public let bridgeToSwift: UnsafeDataModelSchema
public required init(_ swiftValue: LegacyXcodeDataModelSchema) { public required init(_ swiftValue: UnsafeDataModelSchema) {
self.bridgeToSwift = swiftValue self.bridgeToSwift = swiftValue
super.init() super.init()
@@ -102,14 +102,14 @@ public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, Core
} }
// MARK: - LegacyXcodeDataModelSchema // MARK: - UnsafeDataModelSchema
extension LegacyXcodeDataModelSchema: CoreStoreSwiftType { extension UnsafeDataModelSchema: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
public var bridgeToObjectiveC: CSLegacyXcodeDataModelSchema { public var bridgeToObjectiveC: CSUnsafeDataModelSchema {
return CSLegacyXcodeDataModelSchema(self) return CSUnsafeDataModelSchema(self)
} }
} }

View File

@@ -47,6 +47,10 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
self.bridgeToSwift.context.saveAsynchronouslyWithCompletion { (_, error) in self.bridgeToSwift.context.saveAsynchronouslyWithCompletion { (_, error) in
defer {
withExtendedLifetime(self, {})
}
if let error = error { if let error = error {
failure?(error.bridgeToObjectiveC) failure?(error.bridgeToObjectiveC)
@@ -55,7 +59,6 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
success?() success?()
} }
withExtendedLifetime(self, {})
} }
} }
@@ -217,6 +220,10 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
self.bridgeToSwift.context.saveAsynchronouslyWithCompletion { (hasChanges, error) in self.bridgeToSwift.context.saveAsynchronouslyWithCompletion { (hasChanges, error) in
defer {
withExtendedLifetime(self, {})
}
if let error = error { if let error = error {
completion?(SaveResult(error).bridgeToObjectiveC) completion?(SaveResult(error).bridgeToObjectiveC)
@@ -225,7 +232,6 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
completion?(SaveResult(hasChanges: hasChanges).bridgeToObjectiveC) completion?(SaveResult(hasChanges: hasChanges).bridgeToObjectiveC)
} }
withExtendedLifetime(self, {})
} }
} }

View File

@@ -231,7 +231,9 @@ extension Entity: CustomDebugStringConvertible, CoreStoreDebugStringConvertible
return createFormattedString( return createFormattedString(
"(", ")", "(", ")",
("type", self.type), ("type", self.type),
("entityName", self.entityName) ("entityName", self.entityName),
("isAbstract", self.isAbstract),
("versionHashModifier", self.versionHashModifier as Any)
) )
} }
} }
@@ -372,9 +374,9 @@ extension Into: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
} }
// MARK: - LegacyXcodeDataModelSchema // MARK: - UnsafeDataModelSchema
extension LegacyXcodeDataModelSchema: CustomDebugStringConvertible, CoreStoreDebugStringConvertible { extension UnsafeDataModelSchema: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible // MARK: CustomDebugStringConvertible

View File

@@ -294,7 +294,8 @@ public extension NSError {
} }
switch CocoaError.Code(rawValue: self.code) { switch CocoaError.Code(rawValue: self.code) {
case CocoaError.Code.persistentStoreIncompatibleVersionHash, case CocoaError.Code.persistentStoreIncompatibleSchema,
CocoaError.Code.persistentStoreIncompatibleVersionHash,
CocoaError.Code.migrationMissingSourceModel, CocoaError.Code.migrationMissingSourceModel,
CocoaError.Code.migration: CocoaError.Code.migration:
return true return true

View File

@@ -63,7 +63,7 @@ public extension DataStack {
defer { defer {
withExtendedLifetime(transaction, {}) withExtendedLifetime((self, transaction), {})
} }
let userInfo: T let userInfo: T
do { do {
@@ -112,7 +112,7 @@ public extension DataStack {
defer { defer {
withExtendedLifetime(transaction, {}) withExtendedLifetime((self, transaction), {})
} }
let userInfo: T let userInfo: T
do { do {

View File

@@ -37,16 +37,16 @@ public final class DataStack: Equatable {
/** /**
Convenience initializer for `DataStack` that creates a `SchemaHistory` from the model with the specified `modelName` in the specified `bundle`. Convenience initializer for `DataStack` that creates a `SchemaHistory` from the model with the specified `modelName` in the specified `bundle`.
- parameter modelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set (e.g. in Unit Tests). - parameter xcodeModelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set (e.g. in Unit Tests).
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used. - parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
- parameter migrationChain: 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. - parameter migrationChain: 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.
*/ */
public convenience init(modelName: XcodeDataModelFileName = DataStack.applicationName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) { public convenience init(xcodeModelName: XcodeDataModelFileName = DataStack.applicationName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) {
self.init( self.init(
schemaHistory: SchemaHistory( schemaHistory: SchemaHistory(
XcodeDataModelSchema.from( XcodeDataModelSchema.from(
modelName: modelName, modelName: xcodeModelName,
bundle: bundle, bundle: bundle,
migrationChain: migrationChain migrationChain: migrationChain
), ),
@@ -613,14 +613,25 @@ public final class DataStack: Equatable {
// MARK: Deprecated // MARK: Deprecated
@available(*, deprecated, message: "Use the new DataStack.init(schemaHistory:) initializer passing a LegacyXcodeDataModelSchema instance as argument") @available(*, deprecated, renamed: "init(xcodeModelName:bundle:migrationChain:)")
public convenience init(modelName: XcodeDataModelFileName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) {
self.init(
xcodeModelName: modelName,
bundle: bundle,
migrationChain: migrationChain
)
}
@available(*, deprecated, message: "Use the new DataStack.init(schemaHistory:) initializer passing an UnsafeDataModelSchema instance as argument")
public convenience init(model: NSManagedObjectModel, migrationChain: MigrationChain = nil) { public convenience init(model: NSManagedObjectModel, migrationChain: MigrationChain = nil) {
let modelVersion = migrationChain.leafVersions.first! let modelVersion = migrationChain.leafVersions.first!
self.init( self.init(
schemaHistory: SchemaHistory( schemaHistory: SchemaHistory(
allSchema: [ allSchema: [
LegacyXcodeDataModelSchema( UnsafeDataModelSchema(
modelName: modelVersion, modelName: modelVersion,
model: model model: model
) )

View File

@@ -48,6 +48,11 @@ public protocol DynamicObject: class {
*/ */
static func cs_matches(object: NSManagedObject) -> Bool static func cs_matches(object: NSManagedObject) -> Bool
/**
Used internally by CoreStore. Do not call directly.
*/
func cs_id() -> NSManagedObjectID
/** /**
Used internally by CoreStore. Do not call directly. Used internally by CoreStore. Do not call directly.
*/ */
@@ -86,6 +91,11 @@ extension NSManagedObject: DynamicObject {
return object.isKind(of: self) return object.isKind(of: self)
} }
public func cs_id() -> NSManagedObjectID {
return self.objectID
}
public func cs_toRaw() -> NSManagedObject { public func cs_toRaw() -> NSManagedObject {
return self return self
@@ -135,6 +145,11 @@ extension CoreStoreObject {
return (self as AnyClass).isSubclass(of: type as AnyClass) return (self as AnyClass).isSubclass(of: type as AnyClass)
} }
public func cs_id() -> NSManagedObjectID {
return self.rawObject!.objectID
}
public func cs_toRaw() -> NSManagedObject { public func cs_toRaw() -> NSManagedObject {
return self.rawObject! return self.rawObject!

View File

@@ -31,6 +31,12 @@ import Foundation
public extension DynamicSchema { public extension DynamicSchema {
/**
Prints the `DynamicSchema` as their corresponding `CoreStoreObject` Swift declarations. This is useful for converting current `XcodeDataModelSchema`-based models into the new `CoreStoreSchema` framework. Additional adjustments may need to be done to the generated source code; for example: `Transformable` concrete types need to be provided, as well as `default` values.
- Important: After transitioning to the new `CoreStoreSchema` framework, it is recommended to add the new schema as a new version that the existing versions' `XcodeDataModelSchema` can migrate to. It is discouraged to load existing SQLite files created with `XcodeDataModelSchema` directly into a `CoreStoreSchema`.
- returns: a string that represents the source code for the `DynamicSchema` as their corresponding `CoreStoreObject` Swift declarations.
*/
public func printCoreStoreSchema() -> String { public func printCoreStoreSchema() -> String {
let model = self.rawModel() let model = self.rawModel()
@@ -147,8 +153,7 @@ public extension DynamicSchema {
} }
case .dateAttributeType: case .dateAttributeType:
valueType = Date.self valueType = Date.self
if let defaultValue = (attribute.defaultValue as! Date.ImportableNativeType?).flatMap(Date.cs_fromImportableNativeType), if let defaultValue = (attribute.defaultValue as! Date.ImportableNativeType?).flatMap(Date.cs_fromImportableNativeType) {
defaultValue != Date.cs_emptyValue() {
defaultString = ", default: Date(timeIntervalSinceReferenceDate: \(defaultValue.timeIntervalSinceReferenceDate))" defaultString = ", default: Date(timeIntervalSinceReferenceDate: \(defaultValue.timeIntervalSinceReferenceDate))"
} }
@@ -188,9 +193,11 @@ public extension DynamicSchema {
let indexedString = attribute.isIndexed ? ", isIndexed: true" : "" let indexedString = attribute.isIndexed ? ", isIndexed: true" : ""
let transientString = attribute.isTransient ? ", isTransient: true" : "" let transientString = attribute.isTransient ? ", isTransient: true" : ""
// TODO: escape strings // TODO: escape strings
let versionHashModifierString = attribute.versionHashModifier.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? "" let versionHashModifierString = attribute.versionHashModifier
.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
// TODO: escape strings // TODO: escape strings
let renamingIdentifierString = attribute.renamingIdentifier.flatMap({ ", renamingIdentifier: \"\($0)\"" }) ?? "" let renamingIdentifierString = attribute.renamingIdentifier
.flatMap({ ($0 == attributeName ? "" : ", renamingIdentifier: \"\($0)\"") as String }) ?? ""
output.append(" let \(attributeName) = \(containerType)<\(String(describing: valueType))>(\"\(attributeName)\"\(indexedString)\(defaultString)\(transientString)\(versionHashModifierString)\(renamingIdentifierString))\n") output.append(" let \(attributeName) = \(containerType)<\(String(describing: valueType))>(\"\(attributeName)\"\(indexedString)\(defaultString)\(transientString)\(versionHashModifierString)\(renamingIdentifierString))\n")
} }
} }
@@ -255,8 +262,10 @@ public extension DynamicSchema {
fatalError("Unsupported delete rule \((relationship.deleteRule)) for relationship \"\(relationshipQualifier)\"") fatalError("Unsupported delete rule \((relationship.deleteRule)) for relationship \"\(relationshipQualifier)\"")
} }
} }
let versionHashModifierString = relationship.versionHashModifier.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? "" let versionHashModifierString = relationship.versionHashModifier
let renamingIdentifierString = relationship.renamingIdentifier.flatMap({ ", renamingIdentifier: \"\($0)\"" }) ?? "" .flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
let renamingIdentifierString = relationship.renamingIdentifier
.flatMap({ ($0 == relationshipName ? "" : ", renamingIdentifier: \"\($0)\"") as String }) ?? ""
output.append(" let \(relationshipName) = \(containerType)<\(relationship.destinationEntity!.name!)>(\"\(relationshipName)\"\(inverseString)\(deleteRuleString)\(minCountString)\(maxCountString)\(versionHashModifierString)\(renamingIdentifierString))\n") output.append(" let \(relationshipName) = \(containerType)<\(relationship.destinationEntity!.name!)>(\"\(relationshipName)\"\(inverseString)\(deleteRuleString)\(minCountString)\(maxCountString)\(versionHashModifierString)\(renamingIdentifierString))\n")
} }
} }

View File

@@ -32,7 +32,7 @@ import Foundation
/** /**
`DynamicSchema` are types that provide `NSManagedObjectModel` instances for a single model version. CoreStore currently supports the following concrete types: `DynamicSchema` are types that provide `NSManagedObjectModel` instances for a single model version. CoreStore currently supports the following concrete types:
- `XcodeDataModelSchema`: describes models loaded from a .xcdatamodeld file. - `XcodeDataModelSchema`: describes models loaded from a .xcdatamodeld file.
- `LegacyXcodeDataModelSchema`: describes models loaded directly from an existing `NSManagedObjectModel`. It is not advisable to continue using this model as its metadata are not available to CoreStore. - `UnsafeDataModelSchema`: describes models loaded directly from an existing `NSManagedObjectModel`. It is not advisable to continue using this model as its metadata are not available to CoreStore.
- `CoreStoreSchema`: describes models written for `CoreStoreObject` Swift class declarations. - `CoreStoreSchema`: describes models written for `CoreStoreObject` Swift class declarations.
*/ */
public protocol DynamicSchema { public protocol DynamicSchema {

View File

@@ -62,7 +62,6 @@ public final class ICloudStore: CloudStorage {
- parameter ubiquitousContainerID: a container if your app has multiple ubiquity container identifiers in its entitlements - parameter ubiquitousContainerID: a container if your app has multiple ubiquity container identifiers in its entitlements
- parameter ubiquitousPeerToken: a per-application salt to allow multiple apps on the same device to share a Core Data store integrated with iCloud - parameter ubiquitousPeerToken: a per-application salt to allow multiple apps on the same device to share a Core Data store integrated with iCloud
- 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 `ubiquitousContentName` 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 `ubiquitousContentName` explicitly for each of them.
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
- parameter cloudStorageOptions: When the `ICloudStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`. - parameter cloudStorageOptions: When the `ICloudStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`.
*/ */
public required init?(ubiquitousContentName: String, ubiquitousContentTransactionLogsSubdirectory: String, ubiquitousContainerID: String? = nil, ubiquitousPeerToken: String? = nil, configuration: ModelConfiguration = nil, cloudStorageOptions: CloudStorageOptions = nil) { public required init?(ubiquitousContentName: String, ubiquitousContentTransactionLogsSubdirectory: String, ubiquitousContainerID: String? = nil, ubiquitousPeerToken: String? = nil, configuration: ModelConfiguration = nil, cloudStorageOptions: CloudStorageOptions = nil) {

View File

@@ -64,12 +64,6 @@ public protocol ImportableAttributeType: QueryableAttributeType {
*/ */
associatedtype ImportableNativeType: QueryableNativeType associatedtype ImportableNativeType: QueryableNativeType
/**
Returns the default "empty" value for this type.
*/
@inline(__always)
static func cs_emptyValue() -> Self
/** /**
Creates an instance of this type from its `ImportableNativeType` value. Creates an instance of this type from its `ImportableNativeType` value.
*/ */
@@ -84,18 +78,31 @@ public protocol ImportableAttributeType: QueryableAttributeType {
} }
// MARK: - EmptyableAttributeType
/**
`ImportableAttributeType`s that have a natural "empty" value. Example: `0` for `Int`, `""` for `String`.
- Discussion: Not all `ImportableAttributeType`s can have empty values. `URL`s and `Date`s for example have no obvious empty values.
*/
public protocol EmptyableAttributeType: ImportableAttributeType {
/**
Returns the default "empty" value for this type.
*/
@inline(__always)
static func cs_emptyValue() -> Self
}
// MARK: - Bool // MARK: - Bool
extension Bool: ImportableAttributeType { extension Bool: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSNumber public typealias ImportableNativeType = NSNumber
@inline(__always)
public static func cs_emptyValue() -> Bool {
return false
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Bool? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Bool? {
@@ -107,21 +114,26 @@ extension Bool: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@inline(__always)
public static func cs_emptyValue() -> Bool {
return false
}
} }
// MARK: - CGFloat // MARK: - CGFloat
extension CGFloat: ImportableAttributeType { extension CGFloat: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSNumber public typealias ImportableNativeType = NSNumber
@inline(__always)
public static func cs_emptyValue() -> CGFloat {
return 0
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> CGFloat? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> CGFloat? {
@@ -133,21 +145,26 @@ extension CGFloat: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@inline(__always)
public static func cs_emptyValue() -> CGFloat {
return 0
}
} }
// MARK: - Data // MARK: - Data
extension Data: ImportableAttributeType { extension Data: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSData public typealias ImportableNativeType = NSData
@inline(__always)
public static func cs_emptyValue() -> Data {
return Data()
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Data? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Data? {
@@ -159,6 +176,15 @@ extension Data: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@inline(__always)
public static func cs_emptyValue() -> Data {
return Data()
}
} }
@@ -166,13 +192,9 @@ extension Data: ImportableAttributeType {
extension Date: ImportableAttributeType { extension Date: ImportableAttributeType {
public typealias ImportableNativeType = NSDate // MARK: ImportableAttributeType
@inline(__always) public typealias ImportableNativeType = NSDate
public static func cs_emptyValue() -> Date {
return Date(timeIntervalSinceReferenceDate: 0)
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Date? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Date? {
@@ -190,16 +212,12 @@ extension Date: ImportableAttributeType {
// MARK: - Double // MARK: - Double
extension Double: ImportableAttributeType { extension Double: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSNumber public typealias ImportableNativeType = NSNumber
@inline(__always)
public static func cs_emptyValue() -> Double {
return 0
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Double? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Double? {
@@ -211,21 +229,26 @@ extension Double: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@inline(__always)
public static func cs_emptyValue() -> Double {
return 0
}
} }
// MARK: - Float // MARK: - Float
extension Float: ImportableAttributeType { extension Float: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSNumber public typealias ImportableNativeType = NSNumber
@inline(__always)
public static func cs_emptyValue() -> Float {
return 0
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Float? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Float? {
@@ -237,21 +260,26 @@ extension Float: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@inline(__always)
public static func cs_emptyValue() -> Float {
return 0
}
} }
// MARK: - Int // MARK: - Int
extension Int: ImportableAttributeType { extension Int: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSNumber public typealias ImportableNativeType = NSNumber
@inline(__always)
public static func cs_emptyValue() -> Int {
return 0
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int? {
@@ -263,21 +291,26 @@ extension Int: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@inline(__always)
public static func cs_emptyValue() -> Int {
return 0
}
} }
// MARK: - Int8 // MARK: - Int8
extension Int8: ImportableAttributeType { extension Int8: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSNumber public typealias ImportableNativeType = NSNumber
@inline(__always)
public static func cs_emptyValue() -> Int8 {
return 0
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int8? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int8? {
@@ -289,21 +322,26 @@ extension Int8: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@inline(__always)
public static func cs_emptyValue() -> Int8 {
return 0
}
} }
// MARK: - Int16 // MARK: - Int16
extension Int16: ImportableAttributeType { extension Int16: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSNumber public typealias ImportableNativeType = NSNumber
@inline(__always)
public static func cs_emptyValue() -> Int16 {
return 0
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int16? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int16? {
@@ -315,21 +353,26 @@ extension Int16: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@inline(__always)
public static func cs_emptyValue() -> Int16 {
return 0
}
} }
// MARK: - Int32 // MARK: - Int32
extension Int32: ImportableAttributeType { extension Int32: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSNumber public typealias ImportableNativeType = NSNumber
@inline(__always)
public static func cs_emptyValue() -> Int32 {
return 0
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int32? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int32? {
@@ -341,21 +384,26 @@ extension Int32: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@inline(__always)
public static func cs_emptyValue() -> Int32 {
return 0
}
} }
// MARK: - Int64 // MARK: - Int64
extension Int64: ImportableAttributeType { extension Int64: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSNumber public typealias ImportableNativeType = NSNumber
@inline(__always)
public static func cs_emptyValue() -> Int64 {
return 0
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int64? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int64? {
@@ -367,21 +415,26 @@ extension Int64: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@inline(__always)
public static func cs_emptyValue() -> Int64 {
return 0
}
} }
// MARK: - NSData // MARK: - NSData
extension NSData: ImportableAttributeType { extension NSData: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSData public typealias ImportableNativeType = NSData
@nonobjc @inline(__always)
public class func cs_emptyValue() -> Self {
return self.init()
}
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
@@ -393,6 +446,15 @@ extension NSData: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@nonobjc @inline(__always)
public class func cs_emptyValue() -> Self {
return self.init()
}
} }
@@ -400,13 +462,9 @@ extension NSData: ImportableAttributeType {
extension NSDate: ImportableAttributeType { extension NSDate: ImportableAttributeType {
public typealias ImportableNativeType = NSDate // MARK: ImportableAttributeType
@nonobjc @inline(__always) public typealias ImportableNativeType = NSDate
public class func cs_emptyValue() -> Self {
return self.init(timeIntervalSinceReferenceDate: 0)
}
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
@@ -424,16 +482,12 @@ extension NSDate: ImportableAttributeType {
// MARK: - NSNumber // MARK: - NSNumber
extension NSNumber: ImportableAttributeType { extension NSNumber: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSNumber public typealias ImportableNativeType = NSNumber
@nonobjc @inline(__always)
public class func cs_emptyValue() -> Self {
return self.init()
}
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
@@ -445,21 +499,26 @@ extension NSNumber: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@nonobjc @inline(__always)
public class func cs_emptyValue() -> Self {
return self.init()
}
} }
// MARK: - NSString // MARK: - NSString
extension NSString: ImportableAttributeType { extension NSString: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSString public typealias ImportableNativeType = NSString
@nonobjc @inline(__always)
public class func cs_emptyValue() -> Self {
return self.init()
}
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
@@ -471,6 +530,15 @@ extension NSString: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@nonobjc @inline(__always)
public class func cs_emptyValue() -> Self {
return self.init()
}
} }
@@ -478,13 +546,9 @@ extension NSString: ImportableAttributeType {
extension NSURL: ImportableAttributeType { extension NSURL: ImportableAttributeType {
public typealias ImportableNativeType = NSString // MARK: ImportableAttributeType
@nonobjc @inline(__always) public typealias ImportableNativeType = NSString
public class func cs_emptyValue() -> Self {
return self.init(string: "")!
}
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
@@ -504,16 +568,9 @@ extension NSURL: ImportableAttributeType {
extension NSUUID: ImportableAttributeType { extension NSUUID: ImportableAttributeType {
public typealias ImportableNativeType = NSString // MARK: ImportableAttributeType
public class func cs_emptyValue() -> Self { public typealias ImportableNativeType = NSString
enum Static {
static var zero = Array<UInt8>(repeating: 0, count: 16)
}
return self.init(uuidBytes: &Static.zero)
}
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
@@ -531,16 +588,12 @@ extension NSUUID: ImportableAttributeType {
// MARK: - String // MARK: - String
extension String: ImportableAttributeType { extension String: ImportableAttributeType, EmptyableAttributeType {
// MARK: ImportableAttributeType
public typealias ImportableNativeType = NSString public typealias ImportableNativeType = NSString
@inline(__always)
public static func cs_emptyValue() -> String {
return ""
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> String? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> String? {
@@ -552,6 +605,15 @@ extension String: ImportableAttributeType {
return self.cs_toQueryableNativeType() return self.cs_toQueryableNativeType()
} }
// MARK: EmptyableAttributeType
@inline(__always)
public static func cs_emptyValue() -> String {
return ""
}
} }
@@ -559,16 +621,9 @@ extension String: ImportableAttributeType {
extension URL: ImportableAttributeType { extension URL: ImportableAttributeType {
public typealias ImportableNativeType = NSString // MARK: ImportableAttributeType
public static func cs_emptyValue() -> URL { public typealias ImportableNativeType = NSString
enum Static {
static let empty = URL(string: "")!
}
return Static.empty
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> URL? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> URL? {
@@ -588,20 +643,9 @@ extension URL: ImportableAttributeType {
extension UUID: ImportableAttributeType { extension UUID: ImportableAttributeType {
public typealias ImportableNativeType = NSString // MARK: ImportableAttributeType
public static func cs_emptyValue() -> UUID { public typealias ImportableNativeType = NSString
enum Static {
static let empty: UUID = cs_lazy {
var zero = Array<UInt8>(repeating: 0, count: 16)
return NSUUID(uuidBytes: &zero) as UUID
}
}
return Static.empty
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> UUID? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> UUID? {
@@ -623,11 +667,6 @@ extension RawRepresentable where RawValue: ImportableAttributeType {
public typealias ImportableNativeType = RawValue.ImportableNativeType public typealias ImportableNativeType = RawValue.ImportableNativeType
public static func cs_emptyValue() -> Self {
return self.init(rawValue: RawValue.cs_emptyValue())!
}
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {

View File

@@ -56,8 +56,7 @@ public protocol ListObserver: class {
func listMonitorWillChange(_ monitor: ListMonitor<ListEntityType>) func listMonitorWillChange(_ monitor: ListMonitor<ListEntityType>)
/** /**
Handles processing right after a change to the observed list occurs. (Optional) Handles processing right after a change to the observed list occurs. (Required)
The default implementation does nothing.
- parameter monitor: the `ListMonitor` monitoring the object being observed - parameter monitor: the `ListMonitor` monitoring the object being observed
*/ */
@@ -65,17 +64,16 @@ public protocol ListObserver: class {
/** /**
This method is broadcast from within the `ListMonitor`'s `refetch(...)` method to let observers prepare for the internal `NSFetchedResultsController`'s pending change to its predicate, sort descriptors, etc. (Optional) This method is broadcast from within the `ListMonitor`'s `refetch(...)` method to let observers prepare for the internal `NSFetchedResultsController`'s pending change to its predicate, sort descriptors, etc. (Optional)
The default implementation does nothing.
- Note: The actual refetch will happen after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes
- Important: All `ListMonitor` access between `listMonitorWillRefetch(_:)` and `listMonitorDidRefetch(_:)` will raise and assertion. The actual refetch will happen after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes.
- parameter monitor: the `ListMonitor` monitoring the object being observed - parameter monitor: the `ListMonitor` monitoring the object being observed
*/ */
func listMonitorWillRefetch(_ monitor: ListMonitor<ListEntityType>) func listMonitorWillRefetch(_ monitor: ListMonitor<ListEntityType>)
/** /**
After the `ListMonitor`'s `refetch(...)` method is called, this method is broadcast after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes. (Optional) After the `ListMonitor`'s `refetch(...)` method is called, this method is broadcast after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes. (Required)
The default implementation does nothing.
- Important: When `listMonitorDidRefetch(_:)` is called it should be assumed that all `ListMonitor`'s previous data have been reset, including counts, objects, and persistent stores.
- parameter monitor: the `ListMonitor` monitoring the object being observed - parameter monitor: the `ListMonitor` monitoring the object being observed
*/ */
func listMonitorDidRefetch(_ monitor: ListMonitor<ListEntityType>) func listMonitorDidRefetch(_ monitor: ListMonitor<ListEntityType>)
@@ -89,11 +87,7 @@ public extension ListObserver {
public func listMonitorWillChange(_ monitor: ListMonitor<ListEntityType>) { } public func listMonitorWillChange(_ monitor: ListMonitor<ListEntityType>) { }
public func listMonitorDidChange(_ monitor: ListMonitor<ListEntityType>) { }
public func listMonitorWillRefetch(_ monitor: ListMonitor<ListEntityType>) { } public func listMonitorWillRefetch(_ monitor: ListMonitor<ListEntityType>) { }
public func listMonitorDidRefetch(_ monitor: ListMonitor<ListEntityType>) { }
} }

View File

@@ -150,21 +150,43 @@ public extension NSManagedObject {
} }
/** /**
Provides a convenience wrapper for setting `setPrimitiveValue(_:forKey:)` with proper calls to `willChangeValue(forKey:)` and `didChangeValue(forKey:)`. This is useful when implementing mutator methods for transient attributes. Provides a convenience wrapper for setting `setPrimitiveValue(_:forKey:)` with proper calls to `willChangeValue(forKey:)` and `didChangeValue(forKey:)`.
- parameter value: the value to set the KVC key with - parameter value: the value to set the KVC key with
- parameter KVCKey: the KVC key - parameter KVCKey: the KVC key
- parameter willSetValue: called before accessing `setPrimitiveValue(forKey:)`. Callers are allowed to cancel the mutation by throwing an error, for example, for custom validations. - parameter didSetValue: called after executing `setPrimitiveValue(forKey:)`.
*/ */
@nonobjc @inline(__always) @nonobjc @inline(__always)
public func setValue<T>(_ value: T, forKvcKey KVCKey: KeyPath, willSetValue: (T) throws -> Any?) rethrows { public func setValue(_ value: Any?, forKvcKey KVCKey: KeyPath, didSetValue: () -> Void) {
self.willChangeValue(forKey: KVCKey) self.willChangeValue(forKey: KVCKey)
defer { defer {
self.didChangeValue(forKey: KVCKey) self.didChangeValue(forKey: KVCKey)
} }
self.setPrimitiveValue(try willSetValue(value), forKey: KVCKey) self.setPrimitiveValue(value, forKey: KVCKey)
didSetValue()
}
/**
Provides a convenience wrapper for setting `setPrimitiveValue(_:forKey:)` with proper calls to `willChangeValue(forKey:)` and `didChangeValue(forKey:)`. This is useful when implementing mutator methods for transient attributes.
- parameter value: the value to set the KVC key with
- parameter KVCKey: the KVC key
- parameter willSetValue: called before accessing `setPrimitiveValue(forKey:)`. Callers are allowed to cancel the mutation by throwing an error, for example, for custom validations.
- parameter didSetValue: called after executing `setPrimitiveValue(forKey:)`.
*/
@nonobjc @inline(__always)
public func setValue<T>(_ value: T, forKvcKey KVCKey: KeyPath, willSetValue: (T) throws -> Any?, didSetValue: (Any?) -> Void = { _ in }) rethrows {
self.willChangeValue(forKey: KVCKey)
defer {
self.didChangeValue(forKey: KVCKey)
}
let transformedValue = try willSetValue(value)
self.setPrimitiveValue(transformedValue, forKey: KVCKey)
didSetValue(transformedValue)
} }
/** /**

View File

@@ -91,7 +91,7 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
@nonobjc @nonobjc
public func fetchExisting<T: DynamicObject, S: Sequence>(_ objects: S) -> [T] where S.Iterator.Element == T { public func fetchExisting<T: DynamicObject, S: Sequence>(_ objects: S) -> [T] where S.Iterator.Element == T {
return objects.flatMap({ self.fetchExisting($0.cs_toRaw().objectID) }) return objects.flatMap({ self.fetchExisting($0.cs_id()) })
} }
@nonobjc @nonobjc

View File

@@ -260,16 +260,15 @@ public final class ObjectMonitor<D: DynamicObject>: Equatable {
private init(context: NSManagedObjectContext, object: ObjectType) { private init(context: NSManagedObjectContext, object: ObjectType) {
let rawObject = object.cs_toRaw() let objectID = object.cs_id()
let fetchRequest = CoreStoreFetchRequest() let fetchRequest = CoreStoreFetchRequest()
fetchRequest.entity = rawObject.entity fetchRequest.entity = objectID.entity
fetchRequest.fetchLimit = 0 fetchRequest.fetchLimit = 0
fetchRequest.resultType = .managedObjectResultType fetchRequest.resultType = .managedObjectResultType
fetchRequest.sortDescriptors = [] fetchRequest.sortDescriptors = []
fetchRequest.includesPendingChanges = false fetchRequest.includesPendingChanges = false
fetchRequest.shouldRefreshRefetchedObjects = true fetchRequest.shouldRefreshRefetchedObjects = true
let objectID = rawObject.objectID
let fetchedResultsController = CoreStoreFetchedResultsController( let fetchedResultsController = CoreStoreFetchedResultsController(
context: context, context: context,
fetchRequest: fetchRequest.dynamicCast(), fetchRequest: fetchRequest.dynamicCast(),

View File

@@ -41,6 +41,7 @@ public extension DynamicObject where Self: CoreStoreObject {
let pets = Relationship.ToManyUnordered<Dog>("pets", inverse: { $0.master }) let pets = Relationship.ToManyUnordered<Dog>("pets", inverse: { $0.master })
} }
``` ```
- Important: `Relationship` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties.
*/ */
public typealias Relationship = RelationshipContainer<Self> public typealias Relationship = RelationshipContainer<Self>
} }
@@ -73,6 +74,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
let pets = Relationship.ToManyUnordered<Dog>("pets", inverse: { $0.master }) let pets = Relationship.ToManyUnordered<Dog>("pets", inverse: { $0.master })
} }
``` ```
- Important: `Relationship.ToOne` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties.
*/ */
public final class ToOne<D: CoreStoreObject>: RelationshipProtocol { public final class ToOne<D: CoreStoreObject>: RelationshipProtocol {
@@ -251,6 +253,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
let pets = Relationship.ToManyOrdered<Dog>("pets", inverse: { $0.master }) let pets = Relationship.ToManyOrdered<Dog>("pets", inverse: { $0.master })
} }
``` ```
- Important: `Relationship.ToManyOrdered` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties.
*/ */
public final class ToManyOrdered<D: CoreStoreObject>: RelationshipProtocol { public final class ToManyOrdered<D: CoreStoreObject>: RelationshipProtocol {
@@ -442,6 +445,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
let pets = Relationship.ToManyUnordered<Dog>("pets", inverse: { $0.master }) let pets = Relationship.ToManyUnordered<Dog>("pets", inverse: { $0.master })
} }
``` ```
- Important: `Relationship.ToManyUnordered` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties.
*/ */
public final class ToManyUnordered<D: CoreStoreObject>: RelationshipProtocol { public final class ToManyUnordered<D: CoreStoreObject>: RelationshipProtocol {

View File

@@ -70,7 +70,7 @@ public final class SQLiteStore: LocalStorage {
} }
/** /**
Initializes an `SQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `.AllowProgresiveMigration`. Initializes an `SQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `migrationMappingProviders` set to empty, 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 the `SQLiteStore.legacy(...)` factory methods to create the `SQLiteStore` instead of using initializers directly. - 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 the `SQLiteStore.legacy(...)` factory methods to create the `SQLiteStore` instead of using initializers directly.
*/ */
@@ -103,7 +103,7 @@ public final class SQLiteStore: LocalStorage {
} }
/** /**
Initializes an `LegacySQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.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`. Initializes an `LegacySQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support" directory (or the "Caches" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `migrationMappingProviders` set to empty, 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 the `SQLiteStore.legacy(...)` factory methods to create the `SQLiteStore` instead of using initializers directly. - 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 the `SQLiteStore.legacy(...)` factory methods to create the `SQLiteStore` instead of using initializers directly.
*/ */

View File

@@ -1,5 +1,5 @@
// //
// LegacyXcodeDataModelSchema.swift // UnsafeDataModelSchema.swift
// CoreStore // CoreStore
// //
// Copyright © 2017 John Rommel Estropia // Copyright © 2017 John Rommel Estropia
@@ -27,18 +27,18 @@ import CoreData
import Foundation import Foundation
// MARK: - LegacyXcodeDataModelSchema // MARK: - UnsafeDataModelSchema
/** /**
The `LegacyXcodeDataModelSchema` describes models loaded directly from an existing `NSManagedObjectModel`. It is not advisable to continue using this model as its metadata are not available to CoreStore. The `UnsafeDataModelSchema` describes models loaded directly from an existing `NSManagedObjectModel`. It is not advisable to continue using this model as its metadata are not available to CoreStore.
*/ */
public final class LegacyXcodeDataModelSchema: DynamicSchema { public final class UnsafeDataModelSchema: DynamicSchema {
/** /**
Initializes a `LegacyXcodeDataModelSchema` from an `NSManagedObjectModel`. Initializes a `UnsafeDataModelSchema` from an `NSManagedObjectModel`.
``` ```
CoreStore.defaultStack = DataStack( CoreStore.defaultStack = DataStack(
LegacyXcodeDataModelSchema(modelName: "MyAppV1", model: model) UnsafeDataModelSchema(modelName: "MyAppV1", model: model)
) )
``` ```
- parameter modelName: the model version, typically the file name of an *.xcdatamodeld file (without the file extension) - parameter modelName: the model version, typically the file name of an *.xcdatamodeld file (without the file extension)

View File

@@ -40,6 +40,7 @@ public extension DynamicObject where Self: CoreStoreObject {
let color = Transformable.Optional<UIColor>("color") let color = Transformable.Optional<UIColor>("color")
} }
``` ```
- Important: `Value` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties.
*/ */
public typealias Value = ValueContainer<Self> public typealias Value = ValueContainer<Self>
@@ -52,6 +53,7 @@ public extension DynamicObject where Self: CoreStoreObject {
let color = Transformable.Optional<UIColor>("color") let color = Transformable.Optional<UIColor>("color")
} }
``` ```
- Important: `Transformable` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties.
*/ */
public typealias Transformable = TransformableContainer<Self> public typealias Transformable = TransformableContainer<Self>
} }
@@ -82,6 +84,7 @@ public enum ValueContainer<O: CoreStoreObject> {
let color = Transformable.Optional<UIColor>("color") let color = Transformable.Optional<UIColor>("color")
} }
``` ```
- Important: `Value.Required` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties.
*/ */
public final class Required<V: ImportableAttributeType>: AttributeProtocol { public final class Required<V: ImportableAttributeType>: AttributeProtocol {
@@ -99,7 +102,7 @@ public enum ValueContainer<O: CoreStoreObject> {
} }
``` ```
- parameter keyPath: the permanent attribute name for this property. - parameter keyPath: the permanent attribute name for this property.
- parameter default: the initial value for the property when the object is first created. Defaults to the `ImportableAttributeType`'s empty value if not specified. - parameter default: the initial value for the property when the object is first created. For types that implement `EmptyableAttributeType`s, this argument may be omitted and the type's "empty" value will be used instead (e.g. `false` for `Bool`, `0` for `Int`, `""` for `String`, etc.)
- parameter isIndexed: `true` if the property should be indexed for searching, otherwise `false`. Defaults to `false` if not specified. - parameter isIndexed: `true` if the property should be indexed for searching, otherwise `false`. Defaults to `false` if not specified.
- parameter isTransient: `true` if the property is transient, otherwise `false`. Defaults to `false` if not specified. The transient flag specifies whether or not a property's value is ignored when an object is saved to a persistent store. Transient properties are not saved to the persistent store, but are still managed for undo, redo, validation, and so on. - parameter isTransient: `true` if the property is transient, otherwise `false`. Defaults to `false` if not specified. The transient flag specifies whether or not a property's value is ignored when an object is saved to a persistent store. Transient properties are not saved to the persistent store, but are still managed for undo, redo, validation, and so on.
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the properties are unchanged but the format or content of its data are changed.) - parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the properties are unchanged but the format or content of its data are changed.)
@@ -112,7 +115,7 @@ public enum ValueContainer<O: CoreStoreObject> {
- parameter finalNewValue: the transformed new value - parameter finalNewValue: the transformed new value
- parameter originalNewValue: the original new value - parameter originalNewValue: the original new value
*/ */
public init(_ keyPath: KeyPath, `default`: V = V.cs_emptyValue(), isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V) -> V = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (_ finalNewValue: V) -> Void, _ originalNewValue: V) -> Void = { $1($2) }) { public init(_ keyPath: KeyPath, `default`: V, isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V) -> V = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (_ finalNewValue: V) -> Void, _ originalNewValue: V) -> Void = { $1($2) }) {
self.keyPath = keyPath self.keyPath = keyPath
self.isIndexed = isIndexed self.isIndexed = isIndexed
@@ -214,6 +217,7 @@ public enum ValueContainer<O: CoreStoreObject> {
let color = Transformable.Optional<UIColor>("color") let color = Transformable.Optional<UIColor>("color")
} }
``` ```
- Important: `Value.Optional` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties.
*/ */
public final class Optional<V: ImportableAttributeType>: AttributeProtocol { public final class Optional<V: ImportableAttributeType>: AttributeProtocol {
@@ -334,6 +338,43 @@ public enum ValueContainer<O: CoreStoreObject> {
} }
} }
public extension ValueContainer.Required where V: EmptyableAttributeType {
/**
Initializes the metadata for the property. This convenience initializer uses the `EmptyableAttributeType`'s "empty" value as the initial value for the property when the object is first created (e.g. `false` for `Bool`, `0` for `Int`, `""` for `String`, etc.)
```
class Person: CoreStoreObject {
let title = Value.Required<String>("title") // initial value defaults to empty string
}
```
- parameter keyPath: the permanent attribute name for this property.
- parameter isIndexed: `true` if the property should be indexed for searching, otherwise `false`. Defaults to `false` if not specified.
- parameter isTransient: `true` if the property is transient, otherwise `false`. Defaults to `false` if not specified. The transient flag specifies whether or not a property's value is ignored when an object is saved to a persistent store. Transient properties are not saved to the persistent store, but are still managed for undo, redo, validation, and so on.
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the properties are unchanged but the format or content of its data are changed.)
- parameter renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's name.
- parameter customGetter: use this closure to make final transformations to the property's value before returning from the getter.
- parameter self: the `CoreStoreObject`
- parameter getValue: the original getter for the property
- parameter customSetter: use this closure to make final transformations to the new value before assigning to the property.
- parameter setValue: the original setter for the property
- parameter finalNewValue: the transformed new value
- parameter originalNewValue: the original new value
*/
public convenience init(_ keyPath: KeyPath, isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V) -> V = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (_ finalNewValue: V) -> Void, _ originalNewValue: V) -> Void = { $1($2) }) {
self.init(
keyPath,
default: V.cs_emptyValue(),
isIndexed: isIndexed,
isTransient: isTransient,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
customGetter: customGetter,
customSetter: customSetter
)
}
}
// MARK: - TransformableContainer // MARK: - TransformableContainer
@@ -360,6 +401,7 @@ public enum TransformableContainer<O: CoreStoreObject> {
let color = Transformable.Optional<UIColor>("color") let color = Transformable.Optional<UIColor>("color")
} }
``` ```
- Important: `Transformable.Required` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties.
*/ */
public final class Required<V: NSCoding & NSCopying>: AttributeProtocol { public final class Required<V: NSCoding & NSCopying>: AttributeProtocol {
@@ -485,6 +527,7 @@ public enum TransformableContainer<O: CoreStoreObject> {
let color = Transformable.Optional<UIColor>("color") let color = Transformable.Optional<UIColor>("color")
} }
``` ```
- Important: `Transformable.Optional` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties.
*/ */
public final class Optional<V: NSCoding & NSCopying>: AttributeProtocol { public final class Optional<V: NSCoding & NSCopying>: AttributeProtocol {

View File

@@ -148,7 +148,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable {
self.init(NSPredicate(format: "\(keyPath) == nil")) self.init(NSPredicate(format: "\(keyPath) == nil"))
case let object?: case let object?:
self.init(NSPredicate(format: "\(keyPath) == %@", argumentArray: [object.cs_toRaw().objectID])) self.init(NSPredicate(format: "\(keyPath) == %@", argumentArray: [object.cs_id()]))
} }
} }
@@ -171,7 +171,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable {
*/ */
public init<S: Sequence>(_ keyPath: KeyPath, isMemberOf list: S) where S.Iterator.Element: DynamicObject { public init<S: Sequence>(_ keyPath: KeyPath, isMemberOf list: S) where S.Iterator.Element: DynamicObject {
self.init(NSPredicate(format: "\(keyPath) IN %@", list.map({ $0.cs_toRaw().objectID }) as NSArray)) self.init(NSPredicate(format: "\(keyPath) IN %@", list.map({ $0.cs_id() }) as NSArray))
} }
/** /**