mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-14 07:33:28 +01:00
Compare commits
47 Commits
4.0.0-beta
...
4.0.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5689158b43 | ||
|
|
6fcdf3d011 | ||
|
|
e26573c18e | ||
|
|
801cf8d9f0 | ||
|
|
8c437e19b8 | ||
|
|
9cd3b6c879 | ||
|
|
fe135acbec | ||
|
|
997c5bdcfa | ||
|
|
129f975d96 | ||
|
|
a2e463e58c | ||
|
|
5fd50f0e15 | ||
|
|
0a81736b7a | ||
|
|
f9b6dd0c6a | ||
|
|
0354401b56 | ||
|
|
0304067beb | ||
|
|
ddd83da434 | ||
|
|
fc7df671de | ||
|
|
5fde9030c7 | ||
|
|
d7b07b3f00 | ||
|
|
ddd1ffb29f | ||
|
|
98094000bb | ||
|
|
d5026ef996 | ||
|
|
2cd913b9dd | ||
|
|
ad9520abbc | ||
|
|
c0fc57d10c | ||
|
|
0cf4d303e4 | ||
|
|
6de397958a | ||
|
|
55292a84dc | ||
|
|
981b560d53 | ||
|
|
c4c4dd55cd | ||
|
|
1ddbe20c86 | ||
|
|
da9e8c1550 | ||
|
|
ef0937fec4 | ||
|
|
35885b40de | ||
|
|
d669569196 | ||
|
|
ae919ff3c8 | ||
|
|
1a7a4690d1 | ||
|
|
b9b96d1a35 | ||
|
|
da3a9590ac | ||
|
|
6b3d75bea1 | ||
|
|
d44721fef0 | ||
|
|
3f268e8376 | ||
|
|
303fea4ebe | ||
|
|
77173cdad0 | ||
|
|
1e24a7d739 | ||
|
|
a3b33bedb8 | ||
|
|
eaf7544c50 |
@@ -9,7 +9,7 @@ env:
|
||||
global:
|
||||
- LC_CTYPE=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.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"
|
||||
@@ -25,7 +25,7 @@ matrix:
|
||||
before_install:
|
||||
- gem install cocoapods --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 /
|
||||
- rm "Carthage.pkg"
|
||||
before_script:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "CoreStore"
|
||||
s.version = "4.0.0-beta2"
|
||||
s.version = "4.0.5"
|
||||
s.license = "MIT"
|
||||
s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift"
|
||||
s.homepage = "https://github.com/JohnEstropia/CoreStore"
|
||||
|
||||
@@ -214,10 +214,10 @@
|
||||
B52F743E1E9B8724005F3DAC /* 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 */; };
|
||||
B52F74411E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */; };
|
||||
B52F74421E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */; };
|
||||
B52F74431E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */; };
|
||||
B52F74441E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */; };
|
||||
B52F74411E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */; };
|
||||
B52F74421E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */; };
|
||||
B52F74431E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */; };
|
||||
B52F74441E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */; };
|
||||
B52F74451E9B8724005F3DAC /* 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 */; };
|
||||
@@ -238,6 +238,10 @@
|
||||
B538BA781D15B3E30003A766 /* CoreStoreBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B538BA701D15B3E30003A766 /* CoreStoreBridge.m */; };
|
||||
B538BA791D15B3E30003A766 /* CoreStoreBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B538BA701D15B3E30003A766 /* CoreStoreBridge.m */; };
|
||||
B538BA7A1D15B3E30003A766 /* CoreStoreBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B538BA701D15B3E30003A766 /* CoreStoreBridge.m */; };
|
||||
B53B275F1EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */; };
|
||||
B53B27601EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */; };
|
||||
B53B27611EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */; };
|
||||
B53B27621EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */; };
|
||||
B53FB9FE1CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */; };
|
||||
B53FBA001CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */; };
|
||||
B53FBA011CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */; };
|
||||
@@ -426,10 +430,10 @@
|
||||
B56923FB1EB82956007C4DC9 /* 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 */; };
|
||||
B56923FF1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */; };
|
||||
B56924001EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */; };
|
||||
B56924011EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */; };
|
||||
B56924021EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */; };
|
||||
B56923FF1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */; };
|
||||
B56924001EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */; };
|
||||
B56924011EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.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 */; };
|
||||
B56965241B356B820075EE4A /* MigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965231B356B820075EE4A /* MigrationResult.swift */; };
|
||||
B57D27BE1D0BBE8200539C58 /* BaseTestDataTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B57D27BD1D0BBE8200539C58 /* BaseTestDataTestCase.swift */; };
|
||||
@@ -746,12 +750,13 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DispatchQueue+CoreStore.swift"; sourceTree = "<group>"; };
|
||||
B538BA701D15B3E30003A766 /* CoreStoreBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreStoreBridge.m; sourceTree = "<group>"; };
|
||||
B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreManagedObject.swift; sourceTree = "<group>"; };
|
||||
B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSMigrationResult.swift; sourceTree = "<group>"; };
|
||||
B53FBA031CAB300C00F0D40A /* CSMigrationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSMigrationType.swift; sourceTree = "<group>"; };
|
||||
B53FBA0A1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSCoreStore+Migrating.swift"; sourceTree = "<group>"; };
|
||||
@@ -800,7 +805,7 @@
|
||||
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>"; };
|
||||
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; };
|
||||
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>"; };
|
||||
@@ -1108,7 +1113,7 @@
|
||||
B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */,
|
||||
B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */,
|
||||
B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */,
|
||||
B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */,
|
||||
B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */,
|
||||
);
|
||||
name = "Dynamic Schema";
|
||||
sourceTree = "<group>";
|
||||
@@ -1190,7 +1195,7 @@
|
||||
children = (
|
||||
B56923F41EB828BF007C4DC9 /* CSDynamicSchema.swift */,
|
||||
B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */,
|
||||
B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */,
|
||||
B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */,
|
||||
);
|
||||
name = "Dynamic Schema";
|
||||
sourceTree = "<group>";
|
||||
@@ -1425,16 +1430,17 @@
|
||||
children = (
|
||||
B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */,
|
||||
B526613F1CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift */,
|
||||
B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */,
|
||||
B56923C31EB823B4007C4DC9 /* NSEntityDescription+Migration.swift */,
|
||||
B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */,
|
||||
B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */,
|
||||
B51260921E9B28F100402229 /* EntityIdentifier.swift */,
|
||||
B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */,
|
||||
B5E834BA1B7691F3001D3D50 /* Functions.swift */,
|
||||
B5FAD6AB1B51285300714891 /* MigrationManager.swift */,
|
||||
B5E84F2B1AFF849C0064E85B /* NotificationObserver.swift */,
|
||||
B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */,
|
||||
B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */,
|
||||
B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */,
|
||||
B56923C31EB823B4007C4DC9 /* NSEntityDescription+Migration.swift */,
|
||||
B58D0C621EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift */,
|
||||
B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */,
|
||||
B5E84F2C1AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift */,
|
||||
B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */,
|
||||
B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */,
|
||||
@@ -1788,7 +1794,7 @@
|
||||
B5E1B5981CAA0C23007FD580 /* CSObjectObserver.swift in Sources */,
|
||||
B5519A5F1CA21954002BEF78 /* CSAsynchronousDataTransaction.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 */,
|
||||
B5A9921F1EA898710091A2E3 /* UserInfo.swift in Sources */,
|
||||
B54A6A551BA15F2A007870FD /* FetchedResultsControllerDelegate.swift in Sources */,
|
||||
@@ -1875,6 +1881,7 @@
|
||||
B5E2222A1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */,
|
||||
B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */,
|
||||
B56923E81EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
|
||||
B53B275F1EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
|
||||
B5D33A011E96012400C880DE /* Relationship.swift in Sources */,
|
||||
B5E84EE81AFF84610064E85B /* CoreStoreLogger.swift in Sources */,
|
||||
B56923C91EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */,
|
||||
@@ -1900,7 +1907,7 @@
|
||||
B5A991EC1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
|
||||
B5FE4DA71C84FB4400FA6A91 /* InMemoryStore.swift in Sources */,
|
||||
B52F743D1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
|
||||
B56923FF1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */,
|
||||
B56923FF1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
|
||||
B5ECDBEC1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
|
||||
B56923EC1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
|
||||
B5E834B91B76311F001D3D50 /* BaseDataTransaction+Importing.swift in Sources */,
|
||||
@@ -1972,7 +1979,7 @@
|
||||
B5E1B59A1CAA0C23007FD580 /* CSObjectObserver.swift in Sources */,
|
||||
B5519A601CA21954002BEF78 /* CSAsynchronousDataTransaction.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 */,
|
||||
B5A992201EA898720091A2E3 /* UserInfo.swift in Sources */,
|
||||
B5FE4DAD1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */,
|
||||
@@ -2059,6 +2066,7 @@
|
||||
82BA18A71C4BBD2900A0916E /* CoreStore+Logging.swift in Sources */,
|
||||
82BA18D81C4BBD7100A0916E /* WeakObject.swift in Sources */,
|
||||
B56923E91EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
|
||||
B53B27601EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
|
||||
B5D33A021E96012400C880DE /* Relationship.swift in Sources */,
|
||||
B559CD4B1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */,
|
||||
B56923CA1EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */,
|
||||
@@ -2084,7 +2092,7 @@
|
||||
B5A991ED1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
|
||||
B5ECDBEE1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
|
||||
B52F743E1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
|
||||
B56924001EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */,
|
||||
B56924001EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
|
||||
82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */,
|
||||
B56923ED1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
|
||||
82BA18B91C4BBD4A00A0916E /* From.swift in Sources */,
|
||||
@@ -2156,7 +2164,7 @@
|
||||
B5ECDC211CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */,
|
||||
B52DD1C21BE1F94600949AFE /* MigrationManager.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 */,
|
||||
B5A992221EA898720091A2E3 /* UserInfo.swift in Sources */,
|
||||
B5D7A5BA1CA3BF8F005C752B /* CSInto.swift in Sources */,
|
||||
@@ -2243,6 +2251,7 @@
|
||||
B52DD1A71BE1F93200949AFE /* BaseDataTransaction+Querying.swift in Sources */,
|
||||
B546F96C1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
|
||||
B56923EB1EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
|
||||
B53B27621EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
|
||||
B5D33A041E96012400C880DE /* Relationship.swift in Sources */,
|
||||
B52DD1C61BE1F94600949AFE /* NSManagedObjectContext+CoreStore.swift in Sources */,
|
||||
B56923CC1EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */,
|
||||
@@ -2268,7 +2277,7 @@
|
||||
B5A991EF1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
|
||||
B5220E201D130813009BC71E /* CSObjectMonitor.swift in Sources */,
|
||||
B52F74401E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
|
||||
B56924021EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */,
|
||||
B56924021EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
|
||||
B5220E171D1306DF009BC71E /* UnsafeDataTransaction+Observing.swift in Sources */,
|
||||
B56923EF1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
|
||||
B53FBA081CAB300C00F0D40A /* CSMigrationType.swift in Sources */,
|
||||
@@ -2340,7 +2349,7 @@
|
||||
B5519A611CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
|
||||
B5FE4DAE1C85D44E00FA6A91 /* SQLiteStore.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 */,
|
||||
B5A992211EA898720091A2E3 /* UserInfo.swift in Sources */,
|
||||
B563218C1BD65216006C9394 /* DataStack+Transaction.swift in Sources */,
|
||||
@@ -2427,6 +2436,7 @@
|
||||
B563219F1BD65216006C9394 /* ObjectMonitor.swift in Sources */,
|
||||
B56321B61BD6521C006C9394 /* WeakObject.swift in Sources */,
|
||||
B56923EA1EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
|
||||
B53B27611EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
|
||||
B5D33A031E96012400C880DE /* Relationship.swift in Sources */,
|
||||
B559CD4C1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */,
|
||||
B56923CB1EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */,
|
||||
@@ -2452,7 +2462,7 @@
|
||||
B5A991EE1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
|
||||
B5ECDBEF1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
|
||||
B52F743F1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
|
||||
B56924011EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */,
|
||||
B56924011EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
|
||||
B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */,
|
||||
B56923EE1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
|
||||
B56321861BD65216006C9394 /* CoreStoreLogger.swift in Sources */,
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
import CoreStore
|
||||
|
||||
// MARK: - AppDelegate
|
||||
|
||||
|
||||
@@ -1,36 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="10169.1" systemVersion="15D21" minimumToolsVersion="Automatic">
|
||||
<entity name="Palette" representedClassName="CoreStoreDemo.Palette">
|
||||
<attribute name="brightness" optional="YES" attributeType="Float" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="colorName" optional="YES" transient="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="hue" optional="YES" attributeType="Integer 32" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="saturation" optional="YES" attributeType="Float" defaultValueString="0.0" syncable="YES"/>
|
||||
<userInfo/>
|
||||
</entity>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="12141" systemVersion="16F73" minimumToolsVersion="Xcode 7.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
|
||||
<entity name="Place" representedClassName="CoreStoreDemo.Place" syncable="YES">
|
||||
<attribute name="latitude" optional="YES" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="longitude" optional="YES" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="latitude" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="longitude" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="subtitle" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="title" optional="YES" attributeType="String" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="TimeZone" representedClassName="CoreStoreDemo.TimeZone" syncable="YES">
|
||||
<attribute name="abbreviation" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="daylightSavingTimeOffset" optional="YES" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="hasDaylightSavingTime" optional="YES" attributeType="Boolean" syncable="YES"/>
|
||||
<attribute name="daylightSavingTimeOffset" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="hasDaylightSavingTime" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="secondsFromGMT" optional="YES" attributeType="Integer 32" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="secondsFromGMT" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
|
||||
</entity>
|
||||
<configuration name="FetchingAndQueryingDemo">
|
||||
<memberEntity name="TimeZone"/>
|
||||
</configuration>
|
||||
<configuration name="ObservingDemo">
|
||||
<memberEntity name="Palette"/>
|
||||
</configuration>
|
||||
<configuration name="TransactionsDemo">
|
||||
<memberEntity name="Place"/>
|
||||
</configuration>
|
||||
<elements>
|
||||
<element name="Palette" positionX="261" positionY="189" width="128" height="105"/>
|
||||
<element name="Place" positionX="261" positionY="225" width="128" height="105"/>
|
||||
<element name="TimeZone" positionX="297" positionY="270" width="128" height="120"/>
|
||||
</elements>
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.1</string>
|
||||
<string>4.0.3</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<string>4</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
|
||||
@@ -10,7 +10,7 @@ import UIKit
|
||||
import CoreStore
|
||||
|
||||
|
||||
private struct Static {
|
||||
struct ColorsDemo {
|
||||
|
||||
enum Filter: String {
|
||||
|
||||
@@ -33,8 +33,8 @@ private struct Static {
|
||||
switch self {
|
||||
|
||||
case .all: return Where(true)
|
||||
case .light: return Where("%K >= %@", #keyPath(Palette.brightness), 0.9)
|
||||
case .dark: return Where("%K <= %@", #keyPath(Palette.brightness), 0.4)
|
||||
case .light: return Palette.where({ $0.brightness >= 0.9 })
|
||||
case .dark: return Palette.where({ $0.brightness <= 0.4 })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,25 +45,38 @@ private struct Static {
|
||||
|
||||
self.palettes.refetch(
|
||||
self.filter.whereClause(),
|
||||
OrderBy(.ascending(#keyPath(Palette.hue)))
|
||||
Palette.orderBy(ascending: { $0.hue })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
static let stack: DataStack = {
|
||||
|
||||
return DataStack(
|
||||
CoreStoreSchema(
|
||||
modelVersion: "ColorsDemo",
|
||||
entities: [
|
||||
Entity<Palette>("Palette"),
|
||||
],
|
||||
versionLock: [
|
||||
"Palette": [0x8c25aa53c7c90a28, 0xa243a34d25f1a3a7, 0x56565b6935b6055a, 0x4f988bb257bf274f]
|
||||
]
|
||||
)
|
||||
)
|
||||
}()
|
||||
|
||||
static let palettes: ListMonitor<Palette> = {
|
||||
|
||||
try! CoreStore.addStorageAndWait(
|
||||
try! ColorsDemo.stack.addStorageAndWait(
|
||||
SQLiteStore(
|
||||
fileName: "ColorsDemo.sqlite",
|
||||
configuration: "ObservingDemo",
|
||||
localStorageOptions: .recreateStoreOnModelMismatch
|
||||
)
|
||||
)
|
||||
|
||||
return CoreStore.monitorSectionedList(
|
||||
return ColorsDemo.stack.monitorSectionedList(
|
||||
From<Palette>(),
|
||||
SectionBy(#keyPath(Palette.colorName)),
|
||||
OrderBy(.ascending(#keyPath(Palette.hue)))
|
||||
SectionBy(Palette.keyPath({ $0.colorName })),
|
||||
Palette.orderBy(ascending: { $0.hue })
|
||||
)
|
||||
}()
|
||||
}
|
||||
@@ -77,7 +90,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
deinit {
|
||||
|
||||
Static.palettes.removeObserver(self)
|
||||
ColorsDemo.palettes.removeObserver(self)
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +111,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
]
|
||||
|
||||
let filterBarButton = UIBarButtonItem(
|
||||
title: Static.filter.rawValue,
|
||||
title: ColorsDemo.filter.rawValue,
|
||||
style: .plain,
|
||||
target: self,
|
||||
action: #selector(self.filterBarButtonItemTouched(_:))
|
||||
@@ -113,9 +126,9 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
]
|
||||
self.filterBarButton = filterBarButton
|
||||
|
||||
Static.palettes.addObserver(self)
|
||||
ColorsDemo.palettes.addObserver(self)
|
||||
|
||||
self.setTable(enabled: !Static.palettes.isPendingRefetch)
|
||||
self.setTable(enabled: !ColorsDemo.palettes.isPendingRefetch)
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
@@ -137,19 +150,19 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
|
||||
return Static.palettes.numberOfSections()
|
||||
return ColorsDemo.palettes.numberOfSections()
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
|
||||
return Static.palettes.numberOfObjectsInSection(section)
|
||||
return ColorsDemo.palettes.numberOfObjectsInSection(section)
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "PaletteTableViewCell") as! PaletteTableViewCell
|
||||
|
||||
let palette = Static.palettes[indexPath]
|
||||
let palette = ColorsDemo.palettes[indexPath]
|
||||
cell.colorView?.backgroundColor = palette.color
|
||||
cell.label?.text = palette.colorText
|
||||
|
||||
@@ -165,7 +178,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
self.performSegue(
|
||||
withIdentifier: "ObjectObserverDemoViewController",
|
||||
sender: Static.palettes[indexPath]
|
||||
sender: ColorsDemo.palettes[indexPath]
|
||||
)
|
||||
}
|
||||
|
||||
@@ -174,8 +187,8 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
switch editingStyle {
|
||||
|
||||
case .delete:
|
||||
let palette = Static.palettes[indexPath]
|
||||
CoreStore.perform(
|
||||
let palette = ColorsDemo.palettes[indexPath]
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
transaction.delete(palette)
|
||||
@@ -190,7 +203,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
|
||||
return Static.palettes.sectionInfoAtIndex(section).name
|
||||
return ColorsDemo.palettes.sectionInfoAtIndex(section).name
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +226,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
func listMonitorDidRefetch(_ monitor: ListMonitor<Palette>) {
|
||||
|
||||
self.filterBarButton?.title = Static.filter.rawValue
|
||||
self.filterBarButton?.title = ColorsDemo.filter.rawValue
|
||||
self.tableView.reloadData()
|
||||
self.setTable(enabled: true)
|
||||
}
|
||||
@@ -235,7 +248,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
if let cell = self.tableView.cellForRow(at: indexPath) as? PaletteTableViewCell {
|
||||
|
||||
let palette = Static.palettes[indexPath]
|
||||
let palette = ColorsDemo.palettes[indexPath]
|
||||
cell.colorView?.backgroundColor = palette.color
|
||||
cell.label?.text = palette.colorText
|
||||
}
|
||||
@@ -268,7 +281,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
|
||||
|
||||
CoreStore.perform(
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
transaction.deleteAll(From<Palette>())
|
||||
@@ -279,16 +292,16 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
@IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
|
||||
|
||||
Static.filter = Static.filter.next()
|
||||
ColorsDemo.filter = ColorsDemo.filter.next()
|
||||
}
|
||||
|
||||
@IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
|
||||
|
||||
CoreStore.perform(
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
let palette = transaction.create(Into<Palette>())
|
||||
palette.setInitialValues()
|
||||
palette.setInitialValues(in: transaction)
|
||||
},
|
||||
completion: { _ in }
|
||||
)
|
||||
|
||||
@@ -29,7 +29,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
if let palette = newValue {
|
||||
|
||||
self.monitor = CoreStore.monitorObject(palette)
|
||||
self.monitor = ColorsDemo.stack.monitorObject(palette)
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -50,22 +50,22 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
|
||||
if let palette = CoreStore.fetchOne(From<Palette>(), OrderBy(.ascending(#keyPath(Palette.hue)))) {
|
||||
if let palette = ColorsDemo.stack.fetchOne(From<Palette>(), Palette.orderBy(ascending: { $0.hue })) {
|
||||
|
||||
self.monitor = CoreStore.monitorObject(palette)
|
||||
self.monitor = ColorsDemo.stack.monitorObject(palette)
|
||||
}
|
||||
else {
|
||||
|
||||
_ = try? CoreStore.perform(
|
||||
_ = try? ColorsDemo.stack.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
let palette = transaction.create(Into(Palette.self))
|
||||
palette.setInitialValues()
|
||||
let palette = transaction.create(Into<Palette>())
|
||||
palette.setInitialValues(in: transaction)
|
||||
}
|
||||
)
|
||||
|
||||
let palette = CoreStore.fetchOne(From<Palette>(), OrderBy(.ascending(#keyPath(Palette.hue))))!
|
||||
self.monitor = CoreStore.monitorObject(palette)
|
||||
let palette = ColorsDemo.stack.fetchOne(From<Palette>(), Palette.orderBy(ascending: { $0.hue }))!
|
||||
self.monitor = ColorsDemo.stack.monitorObject(palette)
|
||||
}
|
||||
|
||||
super.init(coder: aDecoder)
|
||||
@@ -121,12 +121,12 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
@IBAction dynamic func hueSliderValueDidChange(_ sender: AnyObject?) {
|
||||
|
||||
let hue = self.hueSlider?.value ?? 0
|
||||
CoreStore.perform(
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { [weak self] (transaction) in
|
||||
|
||||
if let palette = transaction.edit(self?.monitor?.object) {
|
||||
|
||||
palette.hue = Int32(hue)
|
||||
palette.hue .= Int(hue)
|
||||
}
|
||||
},
|
||||
completion: { _ in }
|
||||
@@ -136,12 +136,12 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
@IBAction dynamic func saturationSliderValueDidChange(_ sender: AnyObject?) {
|
||||
|
||||
let saturation = self.saturationSlider?.value ?? 0
|
||||
CoreStore.perform(
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { [weak self] (transaction) in
|
||||
|
||||
if let palette = transaction.edit(self?.monitor?.object) {
|
||||
|
||||
palette.saturation = saturation
|
||||
palette.saturation .= saturation
|
||||
}
|
||||
},
|
||||
completion: { _ in }
|
||||
@@ -151,12 +151,12 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
@IBAction dynamic func brightnessSliderValueDidChange(_ sender: AnyObject?) {
|
||||
|
||||
let brightness = self.brightnessSlider?.value ?? 0
|
||||
CoreStore.perform(
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { [weak self] (transaction) in
|
||||
|
||||
if let palette = transaction.edit(self?.monitor?.object) {
|
||||
|
||||
palette.brightness = brightness
|
||||
palette.brightness .= brightness
|
||||
}
|
||||
},
|
||||
completion: { _ in }
|
||||
@@ -165,7 +165,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
@IBAction dynamic func deleteBarButtonTapped(_ sender: AnyObject?) {
|
||||
|
||||
CoreStore.perform(
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { [weak self] (transaction) in
|
||||
|
||||
transaction.delete(self?.monitor?.object)
|
||||
@@ -176,7 +176,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
func reloadPaletteInfo(_ palette: Palette, changedKeys: Set<String>?) {
|
||||
|
||||
self.colorNameLabel?.text = palette.colorName
|
||||
self.colorNameLabel?.text = palette.colorName.value
|
||||
|
||||
let color = palette.color
|
||||
self.colorNameLabel?.textColor = color
|
||||
@@ -184,17 +184,17 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
self.hsbLabel?.text = palette.colorText
|
||||
|
||||
if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.hue)) == true {
|
||||
if changedKeys == nil || changedKeys?.contains(Palette.keyPath{ $0.hue }) == true {
|
||||
|
||||
self.hueSlider?.value = Float(palette.hue)
|
||||
self.hueSlider?.value = Float(palette.hue.value)
|
||||
}
|
||||
if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.saturation)) == true {
|
||||
if changedKeys == nil || changedKeys?.contains(Palette.keyPath{ $0.saturation }) == true {
|
||||
|
||||
self.saturationSlider?.value = palette.saturation
|
||||
self.saturationSlider?.value = palette.saturation.value
|
||||
}
|
||||
if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.brightness)) == true {
|
||||
if changedKeys == nil || changedKeys?.contains(Palette.keyPath{ $0.brightness }) == true {
|
||||
|
||||
self.brightnessSlider?.value = palette.brightness
|
||||
self.brightnessSlider?.value = palette.brightness.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,64 +14,65 @@ import CoreStore
|
||||
|
||||
// MARK: - Palette
|
||||
|
||||
class Palette: NSManagedObject {
|
||||
|
||||
@NSManaged var hue: Int32
|
||||
@NSManaged var saturation: Float
|
||||
@NSManaged var brightness: Float
|
||||
final class Palette: CoreStoreObject {
|
||||
|
||||
@objc dynamic var colorName: String {
|
||||
let hue = Value.Required<Int>("hue")
|
||||
let saturation = Value.Required<Float>("saturation")
|
||||
let brightness = Value.Required<Float>("brightness")
|
||||
|
||||
let colorName = Value.Optional<String>(
|
||||
"colorName",
|
||||
isTransient: true,
|
||||
customGetter: Palette.getCachedColorName
|
||||
)
|
||||
|
||||
private static func getCachedColorName(_ instance: Palette, _ getValue: () -> String?) -> String? {
|
||||
|
||||
get {
|
||||
if let colorName = getValue() {
|
||||
|
||||
let KVCKey = #keyPath(Palette.colorName)
|
||||
if let colorName = self.getValue(forKvcKey: KVCKey) as? String {
|
||||
|
||||
return colorName
|
||||
}
|
||||
|
||||
let colorName: String
|
||||
switch self.hue % 360 {
|
||||
|
||||
case 0 ..< 20: colorName = "Lower Reds"
|
||||
case 20 ..< 57: colorName = "Oranges and Browns"
|
||||
case 57 ..< 90: colorName = "Yellow-Greens"
|
||||
case 90 ..< 159: colorName = "Greens"
|
||||
case 159 ..< 197: colorName = "Blue-Greens"
|
||||
case 197 ..< 241: colorName = "Blues"
|
||||
case 241 ..< 297: colorName = "Violets"
|
||||
case 297 ..< 331: colorName = "Magentas"
|
||||
default: colorName = "Upper Reds"
|
||||
}
|
||||
|
||||
self.setPrimitiveValue(colorName, forKey: KVCKey)
|
||||
return colorName
|
||||
}
|
||||
set {
|
||||
|
||||
let colorName: String
|
||||
switch instance.hue.value % 360 {
|
||||
|
||||
self.setValue(newValue.cs_toImportableNativeType(), forKvcKey: #keyPath(Palette.colorName))
|
||||
case 0 ..< 20: colorName = "Lower Reds"
|
||||
case 20 ..< 57: colorName = "Oranges and Browns"
|
||||
case 57 ..< 90: colorName = "Yellow-Greens"
|
||||
case 90 ..< 159: colorName = "Greens"
|
||||
case 159 ..< 197: colorName = "Blue-Greens"
|
||||
case 197 ..< 241: colorName = "Blues"
|
||||
case 241 ..< 297: colorName = "Violets"
|
||||
case 297 ..< 331: colorName = "Magentas"
|
||||
default: colorName = "Upper Reds"
|
||||
}
|
||||
|
||||
instance.colorName.primitiveValue = colorName
|
||||
return colorName
|
||||
}
|
||||
}
|
||||
|
||||
extension Palette {
|
||||
|
||||
var color: UIColor {
|
||||
|
||||
return UIColor(
|
||||
hue: CGFloat(self.hue) / 360.0,
|
||||
saturation: CGFloat(self.saturation),
|
||||
brightness: CGFloat(self.brightness),
|
||||
hue: CGFloat(self.hue.value) / 360.0,
|
||||
saturation: CGFloat(self.saturation.value),
|
||||
brightness: CGFloat(self.brightness.value),
|
||||
alpha: 1.0
|
||||
)
|
||||
}
|
||||
|
||||
var colorText: String {
|
||||
|
||||
return "H: \(self.hue)˚, S: \(round(self.saturation * 100.0))%, B: \(round(self.brightness * 100.0))%"
|
||||
return "H: \(self.hue.value)˚, S: \(round(self.saturation.value * 100.0))%, B: \(round(self.brightness.value * 100.0))%"
|
||||
}
|
||||
|
||||
func setInitialValues() {
|
||||
func setInitialValues(in transaction: BaseDataTransaction) {
|
||||
|
||||
self.hue = Int32(arc4random_uniform(360))
|
||||
self.saturation = 1.0
|
||||
self.brightness = Float(arc4random_uniform(70) + 30) / 100.0
|
||||
self.hue .= Int(arc4random_uniform(360))
|
||||
self.saturation .= Float(1.0)
|
||||
self.brightness .= Float(arc4random_uniform(70) + 30) / 100.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
|
||||
case 2?:
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
|
||||
_ = self.dataStack.fetchOne(From<Palette>())
|
||||
_ = self.dataStack.fetchOne(From<Place>())
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
@@ -46,7 +46,7 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
|
||||
|
||||
let modelMetadata = withExtendedLifetime(DataStack(modelName: "MigrationDemo")) {
|
||||
let modelMetadata = withExtendedLifetime(DataStack(xcodeModelName: "MigrationDemo")) {
|
||||
(dataStack: DataStack) -> ModelMetadata in
|
||||
|
||||
let models = self.models
|
||||
@@ -91,6 +91,11 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
}
|
||||
}
|
||||
|
||||
func listMonitorDidRefetch(_ monitor: ListMonitor<NSManagedObject>) {
|
||||
|
||||
self.listMonitorDidChange(monitor)
|
||||
}
|
||||
|
||||
// MARK: UITableViewDataSource
|
||||
|
||||
@objc dynamic func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
@@ -148,7 +153,10 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
label: "Model V1",
|
||||
entityType: OrganismV1.self,
|
||||
schemaHistory: SchemaHistory(
|
||||
modelName: "MigrationDemo",
|
||||
XcodeDataModelSchema.from(
|
||||
modelName: "MigrationDemo",
|
||||
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
|
||||
),
|
||||
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
|
||||
)
|
||||
),
|
||||
@@ -156,7 +164,13 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
label: "Model V2",
|
||||
entityType: OrganismV2.self,
|
||||
schemaHistory: SchemaHistory(
|
||||
modelName: "MigrationDemo",
|
||||
XcodeDataModelSchema.from(
|
||||
modelName: "MigrationDemo",
|
||||
migrationChain: [
|
||||
"MigrationDemo": "MigrationDemoV2",
|
||||
"MigrationDemoV3": "MigrationDemoV2"
|
||||
]
|
||||
),
|
||||
migrationChain: [
|
||||
"MigrationDemo": "MigrationDemoV2",
|
||||
"MigrationDemoV3": "MigrationDemoV2"
|
||||
@@ -167,7 +181,10 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
label: "Model V3",
|
||||
entityType: OrganismV3.self,
|
||||
schemaHistory: SchemaHistory(
|
||||
modelName: "MigrationDemo",
|
||||
XcodeDataModelSchema.from(
|
||||
modelName: "MigrationDemo",
|
||||
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
|
||||
),
|
||||
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ private struct Static {
|
||||
|
||||
static let facebookStack: DataStack = {
|
||||
|
||||
let dataStack = DataStack(modelName: "StackSetupDemo")
|
||||
let dataStack = DataStack(xcodeModelName: "StackSetupDemo")
|
||||
try! dataStack.addStorageAndWait(
|
||||
SQLiteStore(
|
||||
fileName: "AccountsDemo_FB_Male.sqlite",
|
||||
@@ -55,7 +55,7 @@ private struct Static {
|
||||
|
||||
static let twitterStack: DataStack = {
|
||||
|
||||
let dataStack = DataStack(modelName: "StackSetupDemo")
|
||||
let dataStack = DataStack(xcodeModelName: "StackSetupDemo")
|
||||
try! dataStack.addStorageAndWait(
|
||||
SQLiteStore(
|
||||
fileName: "AccountsDemo_TW_Male.sqlite",
|
||||
|
||||
@@ -40,7 +40,7 @@ class BaseTestCase: XCTestCase {
|
||||
func prepareStack<T>(configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> T) -> T {
|
||||
|
||||
let stack = DataStack(
|
||||
modelName: "Model",
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: type(of: self))
|
||||
)
|
||||
do {
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
- (void)test_ThatDataStacks_BridgeCorrectly {
|
||||
|
||||
CSDataStack *dataStack = [[CSDataStack alloc]
|
||||
initWithModelName:@"Model"
|
||||
initWithXcodeModelName:@"Model"
|
||||
bundle:[NSBundle bundleForClass:[self class]]
|
||||
versionChain:nil];
|
||||
XCTAssertNotNil(dataStack);
|
||||
@@ -201,7 +201,7 @@
|
||||
|
||||
[CSCoreStore
|
||||
setDefaultStack:[[CSDataStack alloc]
|
||||
initWithModelName:@"Model"
|
||||
initWithXcodeModelName:@"Model"
|
||||
bundle:[NSBundle bundleForClass:[self class]]
|
||||
versionChain:nil]];
|
||||
[CSCoreStore
|
||||
@@ -253,37 +253,5 @@
|
||||
}
|
||||
[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
|
||||
|
||||
@@ -28,12 +28,18 @@ import XCTest
|
||||
@testable
|
||||
import CoreStore
|
||||
|
||||
#if os(OSX)
|
||||
typealias Color = NSColor
|
||||
#else
|
||||
|
||||
typealias Color = UIColor
|
||||
#endif
|
||||
|
||||
class Animal: CoreStoreObject {
|
||||
|
||||
let species = Value.Required<String>("species", default: "Swift")
|
||||
let master = Relationship.ToOne<Person>("master")
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
let color = Transformable.Optional<Color>("color")
|
||||
}
|
||||
|
||||
class Dog: Animal {
|
||||
@@ -45,15 +51,49 @@ class Dog: Animal {
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
let title = Value.Required<String>("title", default: "Mr.")
|
||||
let name = Value.Required<String>(
|
||||
"name",
|
||||
customGetter: { (`self`, getValue) in
|
||||
let title = Value.Required<String>(
|
||||
"title",
|
||||
default: "Mr.",
|
||||
customSetter: { (`self`, setValue, originalNewValue) in
|
||||
|
||||
return "\(self.title.value) \(getValue())"
|
||||
setValue(originalNewValue)
|
||||
self.displayName .= nil
|
||||
}
|
||||
)
|
||||
let name = Value.Required<String>(
|
||||
"name",
|
||||
customSetter: { (`self`, setValue, originalNewValue) in
|
||||
|
||||
setValue(originalNewValue)
|
||||
self.displayName .= nil
|
||||
}
|
||||
)
|
||||
let displayName = Value.Optional<String>(
|
||||
"displayName",
|
||||
isTransient: true,
|
||||
customGetter: Person.cachedDisplayName(_:_:),
|
||||
affectedByKeyPaths: Person.keyPathsAffectingDisplayName()
|
||||
)
|
||||
let pets = Relationship.ToManyUnordered<Animal>("pets", inverse: { $0.master })
|
||||
|
||||
static func cachedDisplayName(_ instance: Person, _ getValue: () -> String?) -> String? {
|
||||
|
||||
if let cached = getValue() {
|
||||
|
||||
return cached
|
||||
}
|
||||
let primitiveValue = "\(instance.title.value) \(instance.name.value)"
|
||||
instance.displayName .= primitiveValue
|
||||
return primitiveValue
|
||||
}
|
||||
|
||||
static func keyPathsAffectingDisplayName() -> Set<String> {
|
||||
|
||||
return [
|
||||
self.keyPath({ $0.title }),
|
||||
self.keyPath({ $0.name })
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +142,7 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
XCTAssertEqual(animal.species.value, "Sparrow")
|
||||
|
||||
animal.color .= .yellow
|
||||
XCTAssertEqual(animal.color.value, UIColor.yellow)
|
||||
XCTAssertEqual(animal.color.value, Color.yellow)
|
||||
|
||||
let dog = transaction.create(Into<Dog>())
|
||||
XCTAssertEqual(dog.species.value, "Swift")
|
||||
@@ -118,11 +158,25 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
let person = transaction.create(Into<Person>())
|
||||
XCTAssertTrue(person.pets.value.isEmpty)
|
||||
|
||||
XCTAssertEqual(
|
||||
object_getClass(person.rawObject!).keyPathsForValuesAffectingValue(forKey: "displayName"),
|
||||
["title", "name"]
|
||||
)
|
||||
|
||||
person.name .= "Joe"
|
||||
|
||||
XCTAssertEqual(person.rawObject!.value(forKey: "name") as! String?, "Joe")
|
||||
XCTAssertEqual(person.rawObject!.value(forKey: "displayName") as! String?, "Mr. Joe")
|
||||
|
||||
person.rawObject!.setValue("AAAA", forKey: "displayName")
|
||||
XCTAssertEqual(person.rawObject!.value(forKey: "displayName") as! String?, "AAAA")
|
||||
|
||||
person.name .= "John"
|
||||
XCTAssertEqual(person.name.value, "Mr. John") // Custom getter
|
||||
XCTAssertEqual(person.name.value, "John")
|
||||
XCTAssertEqual(person.displayName.value, "Mr. John") // Custom getter
|
||||
|
||||
person.title .= "Sir"
|
||||
XCTAssertEqual(person.name.value, "Sir John")
|
||||
XCTAssertEqual(person.displayName.value, "Sir John")
|
||||
|
||||
person.pets.value.insert(dog)
|
||||
XCTAssertEqual(person.pets.count, 1)
|
||||
@@ -168,7 +222,6 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
success: {
|
||||
|
||||
fetchDone.fulfill()
|
||||
withExtendedLifetime(stack, {})
|
||||
},
|
||||
failure: { _ in
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
let stack = self.expectLogger([.logWarning]) {
|
||||
|
||||
DataStack(
|
||||
modelName: "Model",
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: type(of: self)),
|
||||
migrationChain: migrationChain
|
||||
)
|
||||
@@ -84,7 +84,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
dynamic func test_ThatInMemoryStores_SetupCorrectly() {
|
||||
|
||||
let stack = DataStack(
|
||||
modelName: "Model",
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: type(of: self))
|
||||
)
|
||||
do {
|
||||
@@ -139,7 +139,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
dynamic func test_ThatSQLiteStores_SetupCorrectly() {
|
||||
|
||||
let stack = DataStack(
|
||||
modelName: "Model",
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: type(of: self))
|
||||
)
|
||||
do {
|
||||
@@ -207,7 +207,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
do {
|
||||
|
||||
let stack = DataStack(
|
||||
modelName: "Model",
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: type(of: self))
|
||||
)
|
||||
try! stack.addStorageAndWait(sqliteStore)
|
||||
@@ -226,7 +226,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
|
||||
let metadata = try createStore()
|
||||
let stack = DataStack(
|
||||
modelName: "Model",
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: type(of: self))
|
||||
)
|
||||
try sqliteStore.cs_eraseStorageAndWait(
|
||||
@@ -259,7 +259,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
dynamic func test_ThatLegacySQLiteStores_SetupCorrectly() {
|
||||
|
||||
let stack = DataStack(
|
||||
modelName: "Model",
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: type(of: self))
|
||||
)
|
||||
do {
|
||||
@@ -327,7 +327,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
do {
|
||||
|
||||
let stack = DataStack(
|
||||
modelName: "Model",
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: type(of: self))
|
||||
)
|
||||
try! stack.addStorageAndWait(sqliteStore)
|
||||
@@ -346,7 +346,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
|
||||
let metadata = try createStore()
|
||||
let stack = DataStack(
|
||||
modelName: "Model",
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: type(of: self))
|
||||
)
|
||||
try sqliteStore.cs_eraseStorageAndWait(
|
||||
|
||||
@@ -35,7 +35,7 @@ import CoreData
|
||||
- SeeAlso: `AsynchronousDataTransaction`
|
||||
*/
|
||||
@objc
|
||||
public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
|
||||
public final class CSAsynchronousDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
|
||||
|
||||
/**
|
||||
Saves the transaction changes. This method should not be used after the `-commitWithCompletion:` method was already called once.
|
||||
@@ -139,9 +139,9 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
public typealias SwiftType = AsynchronousDataTransaction
|
||||
|
||||
public override var bridgeToSwift: AsynchronousDataTransaction {
|
||||
public var bridgeToSwift: AsynchronousDataTransaction {
|
||||
|
||||
return super.bridgeToSwift as! AsynchronousDataTransaction
|
||||
return super.swiftTransaction as! AsynchronousDataTransaction
|
||||
}
|
||||
|
||||
public required init(_ swiftValue: AsynchronousDataTransaction) {
|
||||
@@ -149,9 +149,9 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
|
||||
super.init(swiftValue as BaseDataTransaction)
|
||||
}
|
||||
|
||||
public required init(_ swiftValue: BaseDataTransaction) {
|
||||
public required override init(_ swiftValue: BaseDataTransaction) {
|
||||
|
||||
super.init(swiftValue as! AsynchronousDataTransaction)
|
||||
super.init(swiftValue)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public extension CSBaseDataTransaction {
|
||||
@objc
|
||||
public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
|
||||
|
||||
return self.bridgeToSwift.context.fetchExisting(object) as NSManagedObject?
|
||||
return self.swiftTransaction.context.fetchExisting(object) as NSManagedObject?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +52,7 @@ public extension CSBaseDataTransaction {
|
||||
@objc
|
||||
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
|
||||
|
||||
return self.bridgeToSwift.context.fetchExisting(objectID) as NSManagedObject?
|
||||
return self.swiftTransaction.context.fetchExisting(objectID) as NSManagedObject?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,7 +64,7 @@ public extension CSBaseDataTransaction {
|
||||
@objc
|
||||
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
|
||||
|
||||
return self.bridgeToSwift.context.fetchExisting(objects) as [NSManagedObject]
|
||||
return self.swiftTransaction.context.fetchExisting(objects) as [NSManagedObject]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,7 +76,7 @@ public extension CSBaseDataTransaction {
|
||||
@objc
|
||||
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
|
||||
|
||||
return self.bridgeToSwift.context.fetchExisting(objectIDs) as [NSManagedObject]
|
||||
return self.swiftTransaction.context.fetchExisting(objectIDs) as [NSManagedObject]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,10 +90,10 @@ public extension CSBaseDataTransaction {
|
||||
public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
||||
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
return self.bridgeToSwift.context.fetchOne(from, fetchClauses)
|
||||
return self.swiftTransaction.context.fetchOne(from, fetchClauses)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,10 +107,10 @@ public extension CSBaseDataTransaction {
|
||||
public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
||||
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
return self.bridgeToSwift.context.fetchAll(from, fetchClauses)
|
||||
return self.swiftTransaction.context.fetchAll(from, fetchClauses)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,10 +124,10 @@ public extension CSBaseDataTransaction {
|
||||
public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
||||
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
return self.bridgeToSwift.context
|
||||
return self.swiftTransaction.context
|
||||
.fetchCount(from, fetchClauses)
|
||||
.flatMap { NSNumber(value: $0) }
|
||||
}
|
||||
@@ -143,10 +143,10 @@ public extension CSBaseDataTransaction {
|
||||
public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
||||
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
return self.bridgeToSwift.context.fetchObjectID(from, fetchClauses)
|
||||
return self.swiftTransaction.context.fetchObjectID(from, fetchClauses)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,10 +163,10 @@ public extension CSBaseDataTransaction {
|
||||
public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
||||
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
return self.bridgeToSwift.context.queryValue(from, selectClause, queryClauses)
|
||||
return self.swiftTransaction.context.queryValue(from, selectClause, queryClauses)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,9 +183,9 @@ public extension CSBaseDataTransaction {
|
||||
public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
||||
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
return self.bridgeToSwift.context.queryAttributes(from, selectClause, queryClauses)
|
||||
return self.swiftTransaction.context.queryAttributes(from, selectClause, queryClauses)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import CoreData
|
||||
- SeeAlso: `BaseDataTransaction`
|
||||
*/
|
||||
@objc
|
||||
public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
public class CSBaseDataTransaction: NSObject {
|
||||
|
||||
// MARK: Object management
|
||||
|
||||
@@ -45,7 +45,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public var hasChanges: Bool {
|
||||
|
||||
return self.bridgeToSwift.hasChanges
|
||||
return self.swiftTransaction.hasChanges
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +57,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func createInto(_ into: CSInto) -> Any {
|
||||
|
||||
return self.bridgeToSwift.create(into.bridgeToSwift)
|
||||
return self.swiftTransaction.create(into.bridgeToSwift)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,7 +69,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func editObject(_ object: NSManagedObject?) -> Any? {
|
||||
|
||||
return self.bridgeToSwift.edit(object)
|
||||
return self.swiftTransaction.edit(object)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +82,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
|
||||
|
||||
return self.bridgeToSwift.edit(into.bridgeToSwift, objectID)
|
||||
return self.swiftTransaction.edit(into.bridgeToSwift, objectID)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +93,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func deleteObject(_ object: NSManagedObject?) {
|
||||
|
||||
self.bridgeToSwift.delete(object)
|
||||
self.swiftTransaction.delete(object)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,7 +104,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func deleteObjects(_ objects: [NSManagedObject]) {
|
||||
|
||||
self.bridgeToSwift.delete(objects)
|
||||
self.swiftTransaction.delete(objects)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,7 +113,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func refreshAndMergeAllObjects() {
|
||||
|
||||
self.bridgeToSwift.refreshAndMergeAllObjects()
|
||||
self.swiftTransaction.refreshAndMergeAllObjects()
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func insertedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
|
||||
|
||||
return self.bridgeToSwift.insertedObjects(entity)
|
||||
return self.swiftTransaction.insertedObjects(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,7 +139,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func insertedObjectIDs() -> Set<NSManagedObjectID> {
|
||||
|
||||
return self.bridgeToSwift.insertedObjectIDs()
|
||||
return self.swiftTransaction.insertedObjectIDs()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +151,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func insertedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
|
||||
|
||||
return self.bridgeToSwift.insertedObjectIDs(entity)
|
||||
return self.swiftTransaction.insertedObjectIDs(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,7 +163,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func updatedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
|
||||
|
||||
return self.bridgeToSwift.updatedObjects(entity)
|
||||
return self.swiftTransaction.updatedObjects(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,7 +174,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func updatedObjectIDs() -> Set<NSManagedObjectID> {
|
||||
|
||||
return self.bridgeToSwift.updatedObjectIDs()
|
||||
return self.swiftTransaction.updatedObjectIDs()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,7 +186,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func updatedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
|
||||
|
||||
return self.bridgeToSwift.updatedObjectIDs(entity)
|
||||
return self.swiftTransaction.updatedObjectIDs(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +198,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func deletedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
|
||||
|
||||
return self.bridgeToSwift.deletedObjects(entity)
|
||||
return self.swiftTransaction.deletedObjects(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,7 +209,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func deletedObjectIDs() -> Set<NSManagedObjectID> {
|
||||
|
||||
return self.bridgeToSwift.deletedObjectIDs()
|
||||
return self.swiftTransaction.deletedObjectIDs()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +221,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func deletedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
|
||||
|
||||
return self.bridgeToSwift.deletedObjectIDs(entity)
|
||||
return self.swiftTransaction.deletedObjectIDs(entity)
|
||||
}
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
public override var hash: Int {
|
||||
|
||||
return ObjectIdentifier(self.bridgeToSwift).hashValue
|
||||
return ObjectIdentifier(self.swiftTransaction).hashValue
|
||||
}
|
||||
|
||||
public override func isEqual(_ object: Any?) -> Bool {
|
||||
@@ -238,28 +238,20 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
return false
|
||||
}
|
||||
return self.bridgeToSwift === object.bridgeToSwift
|
||||
return self.swiftTransaction === object.swiftTransaction
|
||||
}
|
||||
|
||||
|
||||
// MARK: CoreStoreObjectiveCType
|
||||
// MARK: Internal
|
||||
|
||||
public required init(_ swiftValue: BaseDataTransaction) {
|
||||
internal let swiftTransaction: BaseDataTransaction
|
||||
|
||||
internal init(_ swiftValue: BaseDataTransaction) {
|
||||
|
||||
self.swiftTransaction = swiftValue
|
||||
super.init()
|
||||
}
|
||||
|
||||
public var bridgeToSwift: BaseDataTransaction {
|
||||
|
||||
return self.swiftTransaction
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let swiftTransaction: BaseDataTransaction
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@@ -267,20 +259,20 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func insertedObjects() -> Set<NSManagedObject> {
|
||||
|
||||
return self.bridgeToSwift.insertedObjects()
|
||||
return self.swiftTransaction.insertedObjects()
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "Use -[updatedObjectsOfType:] and pass the specific entity class")
|
||||
@objc
|
||||
public func updatedObjects() -> Set<NSManagedObject> {
|
||||
|
||||
return self.bridgeToSwift.updatedObjects()
|
||||
return self.swiftTransaction.updatedObjects()
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "Use -[deletedObjectsOfType:] and pass the specific entity class")
|
||||
@objc
|
||||
public func deletedObjects() -> Set<NSManagedObject> {
|
||||
|
||||
return self.bridgeToSwift.deletedObjects()
|
||||
return self.swiftTransaction.deletedObjects()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,41 +49,22 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
/**
|
||||
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 versionChain: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(modelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
|
||||
public convenience init(xcodeModelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
|
||||
|
||||
self.init(
|
||||
DataStack(
|
||||
modelName: modelName ?? DataStack.applicationName,
|
||||
xcodeModelName: xcodeModelName ?? DataStack.applicationName,
|
||||
bundle: bundle ?? Bundle.main,
|
||||
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.
|
||||
*/
|
||||
@@ -227,6 +208,19 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
// 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.")
|
||||
@objc
|
||||
public convenience init(model: NSManagedObjectModel, versionChain: [String]?) {
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -35,7 +35,7 @@ import CoreData
|
||||
- SeeAlso: `SynchronousDataTransaction`
|
||||
*/
|
||||
@objc
|
||||
public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
|
||||
public final class CSSynchronousDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
|
||||
|
||||
/**
|
||||
Saves the transaction changes and waits for completion synchronously. This method should not be used after the `-commitAndWaitWithError:` method was already called once.
|
||||
@@ -129,9 +129,9 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
public typealias SwiftType = SynchronousDataTransaction
|
||||
|
||||
public override var bridgeToSwift: SynchronousDataTransaction {
|
||||
public var bridgeToSwift: SynchronousDataTransaction {
|
||||
|
||||
return super.bridgeToSwift as! SynchronousDataTransaction
|
||||
return super.swiftTransaction as! SynchronousDataTransaction
|
||||
}
|
||||
|
||||
public required init(_ swiftValue: SynchronousDataTransaction) {
|
||||
@@ -139,9 +139,9 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
|
||||
super.init(swiftValue as BaseDataTransaction)
|
||||
}
|
||||
|
||||
public required init(_ swiftValue: BaseDataTransaction) {
|
||||
public required override init(_ swiftValue: BaseDataTransaction) {
|
||||
|
||||
super.init(swiftValue as! SynchronousDataTransaction)
|
||||
super.init(swiftValue)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// CSLegacyXcodeDataModelSchema.swift
|
||||
// CSUnsafeDataModelSchema.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
@@ -27,18 +27,18 @@ import CoreData
|
||||
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
|
||||
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 model: the `NSManagedObjectModel`
|
||||
@@ -46,7 +46,7 @@ public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, Core
|
||||
@objc
|
||||
public required init(modelName: ModelVersion, model: NSManagedObjectModel) {
|
||||
|
||||
self.bridgeToSwift = LegacyXcodeDataModelSchema(
|
||||
self.bridgeToSwift = UnsafeDataModelSchema(
|
||||
modelName: modelName,
|
||||
model: model
|
||||
)
|
||||
@@ -62,7 +62,7 @@ public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, Core
|
||||
|
||||
public override func isEqual(_ object: Any?) -> Bool {
|
||||
|
||||
guard let object = object as? CSLegacyXcodeDataModelSchema else {
|
||||
guard let object = object as? CSUnsafeDataModelSchema else {
|
||||
|
||||
return false
|
||||
}
|
||||
@@ -92,9 +92,9 @@ public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, Core
|
||||
|
||||
// MARK: CoreStoreObjectiveCType
|
||||
|
||||
public let bridgeToSwift: LegacyXcodeDataModelSchema
|
||||
public let bridgeToSwift: UnsafeDataModelSchema
|
||||
|
||||
public required init(_ swiftValue: LegacyXcodeDataModelSchema) {
|
||||
public required init(_ swiftValue: UnsafeDataModelSchema) {
|
||||
|
||||
self.bridgeToSwift = swiftValue
|
||||
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
|
||||
|
||||
public var bridgeToObjectiveC: CSLegacyXcodeDataModelSchema {
|
||||
public var bridgeToObjectiveC: CSUnsafeDataModelSchema {
|
||||
|
||||
return CSLegacyXcodeDataModelSchema(self)
|
||||
return CSUnsafeDataModelSchema(self)
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ import CoreData
|
||||
- SeeAlso: `UnsafeDataTransaction`
|
||||
*/
|
||||
@objc
|
||||
public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
public final class CSUnsafeDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
|
||||
/**
|
||||
Saves the transaction changes asynchronously. For a `CSUnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread.
|
||||
|
||||
@@ -47,6 +47,10 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
self.bridgeToSwift.context.saveAsynchronouslyWithCompletion { (_, error) in
|
||||
|
||||
defer {
|
||||
|
||||
withExtendedLifetime(self, {})
|
||||
}
|
||||
if let error = error {
|
||||
|
||||
failure?(error.bridgeToObjectiveC)
|
||||
@@ -55,7 +59,6 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
success?()
|
||||
}
|
||||
withExtendedLifetime(self, {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,9 +189,9 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
public typealias SwiftType = UnsafeDataTransaction
|
||||
|
||||
public override var bridgeToSwift: UnsafeDataTransaction {
|
||||
public var bridgeToSwift: UnsafeDataTransaction {
|
||||
|
||||
return super.bridgeToSwift as! UnsafeDataTransaction
|
||||
return super.swiftTransaction as! UnsafeDataTransaction
|
||||
}
|
||||
|
||||
public required init(_ swiftValue: UnsafeDataTransaction) {
|
||||
@@ -196,9 +199,9 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
super.init(swiftValue as BaseDataTransaction)
|
||||
}
|
||||
|
||||
public required init(_ swiftValue: BaseDataTransaction) {
|
||||
public required override init(_ swiftValue: BaseDataTransaction) {
|
||||
|
||||
super.init(swiftValue as! UnsafeDataTransaction)
|
||||
super.init(swiftValue)
|
||||
}
|
||||
|
||||
|
||||
@@ -217,6 +220,10 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
self.bridgeToSwift.context.saveAsynchronouslyWithCompletion { (hasChanges, error) in
|
||||
|
||||
defer {
|
||||
|
||||
withExtendedLifetime(self, {})
|
||||
}
|
||||
if let error = error {
|
||||
|
||||
completion?(SaveResult(error).bridgeToObjectiveC)
|
||||
@@ -225,7 +232,6 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
completion?(SaveResult(hasChanges: hasChanges).bridgeToObjectiveC)
|
||||
}
|
||||
withExtendedLifetime(self, {})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +231,9 @@ extension Entity: CustomDebugStringConvertible, CoreStoreDebugStringConvertible
|
||||
return createFormattedString(
|
||||
"(", ")",
|
||||
("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
|
||||
|
||||
@@ -983,7 +985,7 @@ extension VersionLock: CustomStringConvertible, CustomDebugStringConvertible, Co
|
||||
string.append(":]")
|
||||
return string
|
||||
}
|
||||
for (index, keyValue) in self.hashesByEntityName.enumerated() {
|
||||
for (index, keyValue) in self.hashesByEntityName.sorted(by: { $0.key < $1.key }).enumerated() {
|
||||
|
||||
let data = keyValue.value
|
||||
let count = data.count
|
||||
|
||||
@@ -294,7 +294,8 @@ public extension NSError {
|
||||
}
|
||||
switch CocoaError.Code(rawValue: self.code) {
|
||||
|
||||
case CocoaError.Code.persistentStoreIncompatibleVersionHash,
|
||||
case CocoaError.Code.persistentStoreIncompatibleSchema,
|
||||
CocoaError.Code.persistentStoreIncompatibleVersionHash,
|
||||
CocoaError.Code.migrationMissingSourceModel,
|
||||
CocoaError.Code.migration:
|
||||
return true
|
||||
|
||||
@@ -35,7 +35,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
|
||||
// MARK: Internal
|
||||
|
||||
@nonobjc
|
||||
internal convenience init<T: DynamicObject>(dataStack: DataStack, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>?, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
|
||||
internal convenience init<T: DynamicObject>(dataStack: DataStack, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
|
||||
|
||||
self.init(
|
||||
context: dataStack.mainContext,
|
||||
@@ -47,33 +47,18 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal init<T: DynamicObject>(context: NSManagedObjectContext, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>?, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
|
||||
internal init<T: DynamicObject>(context: NSManagedObjectContext, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
|
||||
|
||||
_ = from?.applyToFetchRequest(
|
||||
_ = from.applyToFetchRequest(
|
||||
fetchRequest,
|
||||
context: context,
|
||||
applyAffectedStores: false
|
||||
)
|
||||
applyFetchClauses(fetchRequest)
|
||||
|
||||
if let from = from {
|
||||
self.reapplyAffectedStores = { fetchRequest, context in
|
||||
|
||||
self.reapplyAffectedStores = { fetchRequest, context in
|
||||
|
||||
return from.applyAffectedStoresForFetchedRequest(fetchRequest, context: context)
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
guard let from = (fetchRequest.entity.flatMap { $0.managedObjectClassName }).flatMap(NSClassFromString).flatMap({ From<T>($0 as! T.Type) }) else {
|
||||
|
||||
CoreStore.abort("Attempted to create a \(CoreStoreFetchedResultsController.self) without a \(cs_typeName(From<T>.self)) clause or an \(cs_typeName(NSEntityDescription.self)).")
|
||||
}
|
||||
|
||||
self.reapplyAffectedStores = { fetchRequest, context in
|
||||
|
||||
return from.applyAffectedStoresForFetchedRequest(fetchRequest, context: context)
|
||||
}
|
||||
return from.applyAffectedStoresForFetchedRequest(fetchRequest, context: context)
|
||||
}
|
||||
|
||||
super.init(
|
||||
|
||||
34
Sources/CoreStoreManagedObject.swift
Normal file
34
Sources/CoreStoreManagedObject.swift
Normal file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// CoreStoreManagedObject.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Created by John Rommel Estropia on 2017/06/04.
|
||||
// Copyright © 2017 John Rommel Estropia. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - CoreStoreManagedObject
|
||||
|
||||
@objc internal class CoreStoreManagedObject: NSManagedObject {
|
||||
|
||||
internal typealias CustomGetter = @convention(block) (_ rawObject: Any) -> Any?
|
||||
internal typealias CustomSetter = @convention(block) (_ rawObject: Any, _ newValue: Any?) -> Void
|
||||
internal typealias CustomGetterSetter = (getter: CustomGetter?, setter: CustomSetter?)
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
internal static func cs_subclassName(for entity: DynamicEntity, in modelVersion: ModelVersion) -> String {
|
||||
|
||||
return "_\(NSStringFromClass(CoreStoreManagedObject.self))__\(modelVersion)__\(NSStringFromClass(entity.type))__\(entity.entityName)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private enum Static {
|
||||
|
||||
static let queue = DispatchQueue.concurrent("com.coreStore.coreStoreManagerObjectBarrierQueue")
|
||||
static var cache: [ObjectIdentifier: [KeyPath: Set<KeyPath>]] = [:]
|
||||
}
|
||||
@@ -53,6 +53,39 @@ public extension DynamicObject where Self: CoreStoreObject {
|
||||
return attribute(self.meta).keyPath
|
||||
}
|
||||
|
||||
/**
|
||||
Extracts the keyPath string from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let keyPath: String = Person.keyPath { $0.pets }
|
||||
```
|
||||
*/
|
||||
public static func keyPath<O: CoreStoreObject, D: CoreStoreObject>(_ relationship: (Self) -> RelationshipContainer<O>.ToOne<D>) -> String {
|
||||
|
||||
return relationship(self.meta).keyPath
|
||||
}
|
||||
|
||||
/**
|
||||
Extracts the keyPath string from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let keyPath: String = Person.keyPath { $0.pets }
|
||||
```
|
||||
*/
|
||||
public static func keyPath<O: CoreStoreObject, D: CoreStoreObject>(_ relationship: (Self) -> RelationshipContainer<O>.ToManyOrdered<D>) -> String {
|
||||
|
||||
return relationship(self.meta).keyPath
|
||||
}
|
||||
|
||||
/**
|
||||
Extracts the keyPath string from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let keyPath: String = Person.keyPath { $0.pets }
|
||||
```
|
||||
*/
|
||||
public static func keyPath<O: CoreStoreObject, D: CoreStoreObject>(_ relationship: (Self) -> RelationshipContainer<O>.ToManyUnordered<D>) -> String {
|
||||
|
||||
return relationship(self.meta).keyPath
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
@@ -67,10 +100,10 @@ public extension DynamicObject where Self: CoreStoreObject {
|
||||
/**
|
||||
Creates an `OrderBy` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchAll(From<Person>(), Person.ascending { $0.age })
|
||||
let person = CoreStore.fetchAll(From<Person>(), Person.orderBy(ascending: { $0.age }))
|
||||
```
|
||||
*/
|
||||
public static func ascending<O: CoreStoreObject, V: ImportableAttributeType>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
|
||||
public static func orderBy<O: CoreStoreObject, V: ImportableAttributeType>(ascending attribute: (Self) -> ValueContainer<O>.Required<V>) -> OrderBy {
|
||||
|
||||
return OrderBy(.ascending(attribute(self.meta).keyPath))
|
||||
}
|
||||
@@ -78,9 +111,46 @@ public extension DynamicObject where Self: CoreStoreObject {
|
||||
/**
|
||||
Creates an `OrderBy` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchAll(From<Person>(), Person.descending { $0.age })
|
||||
let person = CoreStore.fetchAll(From<Person>(), Person.orderBy(ascending: { $0.age }))
|
||||
```
|
||||
*/
|
||||
public static func orderBy<O: CoreStoreObject, V: ImportableAttributeType>(ascending attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
|
||||
|
||||
return OrderBy(.ascending(attribute(self.meta).keyPath))
|
||||
}
|
||||
|
||||
/**
|
||||
Creates an `OrderBy` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchAll(From<Person>(), Person.orderBy(descending: { $0.age }))
|
||||
```
|
||||
*/
|
||||
public static func orderBy<O: CoreStoreObject, V: ImportableAttributeType>(descending attribute: (Self) -> ValueContainer<O>.Required<V>) -> OrderBy {
|
||||
|
||||
return OrderBy(.descending(attribute(self.meta).keyPath))
|
||||
}
|
||||
|
||||
/**
|
||||
Creates an `OrderBy` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchAll(From<Person>(), Person.orderBy(descending: { $0.age }))
|
||||
```
|
||||
*/
|
||||
public static func orderBy<O: CoreStoreObject, V: ImportableAttributeType>(descending attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
|
||||
|
||||
return OrderBy(.descending(attribute(self.meta).keyPath))
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "orderBy(ascending:)")
|
||||
public static func ascending<O: CoreStoreObject, V: ImportableAttributeType>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
|
||||
|
||||
return OrderBy(.ascending(attribute(self.meta).keyPath))
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "orderBy(descending:)")
|
||||
public static func descending<O: CoreStoreObject, V: ImportableAttributeType>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
|
||||
|
||||
return OrderBy(.descending(attribute(self.meta).keyPath))
|
||||
@@ -163,6 +233,18 @@ public extension ValueContainer.Required {
|
||||
|
||||
return Where("%K >= %@", attribute.keyPath, value)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>(), Dog.where { ["Pluto", "Snoopy", "Scooby"] ~= $0.nickname })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func ~= <S: Sequence>(_ sequence: S, _ attribute: ValueContainer<O>.Required<V>) -> Where where S.Iterator.Element == V {
|
||||
|
||||
return Where(attribute.keyPath, isMemberOf: sequence)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -193,4 +275,146 @@ public extension ValueContainer.Optional {
|
||||
|
||||
return !Where(attribute.keyPath, isEqualTo: value)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchOne(From<Person>(), Person.where { $0.age < 20 })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func < (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where {
|
||||
|
||||
if let value = value {
|
||||
|
||||
return Where("%K < %@", attribute.keyPath, value)
|
||||
}
|
||||
else {
|
||||
|
||||
return Where("%K < nil", attribute.keyPath)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchOne(From<Person>(), Person.where { $0.age > 20 })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func > (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where {
|
||||
|
||||
if let value = value {
|
||||
|
||||
return Where("%K > %@", attribute.keyPath, value)
|
||||
}
|
||||
else {
|
||||
|
||||
return Where("%K > nil", attribute.keyPath)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchOne(From<Person>(), Person.where { $0.age <= 20 })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func <= (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where {
|
||||
|
||||
if let value = value {
|
||||
|
||||
return Where("%K <= %@", attribute.keyPath, value)
|
||||
}
|
||||
else {
|
||||
|
||||
return Where("%K <= nil", attribute.keyPath)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchOne(From<Person>(), Person.where { $0.age >= 20 })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func >= (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where {
|
||||
|
||||
if let value = value {
|
||||
|
||||
return Where("%K >= %@", attribute.keyPath, value)
|
||||
}
|
||||
else {
|
||||
|
||||
return Where("%K >= nil", attribute.keyPath)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>(), Dog.where { ["Pluto", "Snoopy", "Scooby"] ~= $0.nickname })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func ~= <S: Sequence>(_ sequence: S, _ attribute: ValueContainer<O>.Optional<V>) -> Where where S.Iterator.Element == V {
|
||||
|
||||
return Where(attribute.keyPath, isMemberOf: sequence)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - RelationshipContainer.ToOne
|
||||
|
||||
public extension RelationshipContainer.ToOne {
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>(), Dog.where { $0.master == me })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func == (_ relationship: RelationshipContainer<O>.ToOne<D>, _ object: D?) -> Where {
|
||||
|
||||
return Where(relationship.keyPath, isEqualTo: object)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>(), Dog.where { $0.master != me })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func != (_ relationship: RelationshipContainer<O>.ToOne<D>, _ object: D?) -> Where {
|
||||
|
||||
return !Where(relationship.keyPath, isEqualTo: object)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>(), Dog.where { $0.master ~= me })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func ~= (_ relationship: RelationshipContainer<O>.ToOne<D>, _ object: D?) -> Where {
|
||||
|
||||
return Where(relationship.keyPath, isEqualTo: object)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>(), Dog.where { [john, joe, bob] ~= $0.master })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func ~= <S: Sequence>(_ sequence: S, _ relationship: RelationshipContainer<O>.ToOne<D>) -> Where where S.Iterator.Element == D {
|
||||
|
||||
return Where(relationship.keyPath, isMemberOf: sequence)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,8 +68,8 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable {
|
||||
public required init(rawObject: NSManagedObject) {
|
||||
|
||||
self.isMeta = false
|
||||
self.rawObject = rawObject
|
||||
self.initializeAttributes(Mirror(reflecting: self), { [unowned self] in self })
|
||||
self.rawObject = (rawObject as! CoreStoreManagedObject)
|
||||
self.initializeAttributes(Mirror(reflecting: self), self)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,13 +110,13 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal let rawObject: NSManagedObject?
|
||||
internal let rawObject: CoreStoreManagedObject?
|
||||
internal let isMeta: Bool
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private func initializeAttributes(_ mirror: Mirror, _ parentObject: @escaping () -> CoreStoreObject) {
|
||||
private func initializeAttributes(_ mirror: Mirror, _ parentObject: CoreStoreObject) {
|
||||
|
||||
_ = mirror.superclassMirror.flatMap({ self.initializeAttributes($0, parentObject) })
|
||||
for child in mirror.children {
|
||||
|
||||
@@ -187,7 +187,7 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
#if DEBUG
|
||||
CoreStore.log(
|
||||
.notice,
|
||||
message: "These are hashes for the \(cs_typeName(CoreStoreSchema.self)) with version name \"\(modelVersion)\". Copy the dictionary below and pass it to the \(cs_typeName(CoreStoreSchema.self)) initializer's \"versionLock\" argument:\n\(VersionLock(entityVersionHashesByName: self.rawModel().entityVersionHashesByName))"
|
||||
message: "These are hashes for the \(cs_typeName(CoreStoreSchema.self)) with version name \"\(modelVersion)\". Copy the dictionary below and pass it to the \(cs_typeName(CoreStoreSchema.self)) initializer's \"versionLock\" argument:\nversionLock: \(VersionLock(entityVersionHashesByName: self.rawModel().entityVersionHashesByName))"
|
||||
)
|
||||
#endif
|
||||
}
|
||||
@@ -200,35 +200,44 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
|
||||
public func rawModel() -> NSManagedObjectModel {
|
||||
|
||||
if let cachedRawModel = self.cachedRawModel {
|
||||
return CoreStoreSchema.barrierQueue.sync(flags: .barrier) {
|
||||
|
||||
return cachedRawModel
|
||||
}
|
||||
let rawModel = NSManagedObjectModel()
|
||||
var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:]
|
||||
for entity in self.allEntities {
|
||||
|
||||
let entityDescription = self.entityDescription(
|
||||
for: entity,
|
||||
initializer: CoreStoreSchema.firstPassCreateEntityDescription
|
||||
if let cachedRawModel = self.cachedRawModel {
|
||||
|
||||
return cachedRawModel
|
||||
}
|
||||
let rawModel = NSManagedObjectModel()
|
||||
var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:]
|
||||
var allCustomGettersSetters: [DynamicEntity: [KeyPath: CoreStoreManagedObject.CustomGetterSetter]] = [:]
|
||||
for entity in self.allEntities {
|
||||
|
||||
let (entityDescription, customGetterSetterByKeyPaths) = self.entityDescription(
|
||||
for: entity,
|
||||
initializer: CoreStoreSchema.firstPassCreateEntityDescription(from:in:)
|
||||
)
|
||||
entityDescriptionsByEntity[entity] = (entityDescription.copy() as! NSEntityDescription)
|
||||
allCustomGettersSetters[entity] = customGetterSetterByKeyPaths
|
||||
}
|
||||
CoreStoreSchema.secondPassConnectRelationshipAttributes(for: entityDescriptionsByEntity)
|
||||
CoreStoreSchema.thirdPassConnectInheritanceTree(for: entityDescriptionsByEntity)
|
||||
CoreStoreSchema.fourthPassSynthesizeManagedObjectClasses(
|
||||
for: entityDescriptionsByEntity,
|
||||
allCustomGettersSetters: allCustomGettersSetters
|
||||
)
|
||||
entityDescriptionsByEntity[entity] = (entityDescription.copy() as! NSEntityDescription)
|
||||
}
|
||||
CoreStoreSchema.secondPassConnectRelationshipAttributes(for: entityDescriptionsByEntity)
|
||||
CoreStoreSchema.thirdPassConnectInheritanceTree(for: entityDescriptionsByEntity)
|
||||
|
||||
rawModel.entities = entityDescriptionsByEntity.values.sorted(by: { $0.name! < $1.name! })
|
||||
for (configuration, entities) in self.entitiesByConfiguration {
|
||||
|
||||
rawModel.setEntities(
|
||||
entities
|
||||
.map({ entityDescriptionsByEntity[$0]! })
|
||||
.sorted(by: { $0.name! < $1.name! }),
|
||||
forConfigurationName: configuration
|
||||
)
|
||||
rawModel.entities = entityDescriptionsByEntity.values.sorted(by: { $0.name! < $1.name! })
|
||||
for (configuration, entities) in self.entitiesByConfiguration {
|
||||
|
||||
rawModel.setEntities(
|
||||
entities
|
||||
.map({ entityDescriptionsByEntity[$0]! })
|
||||
.sorted(by: { $0.name! < $1.name! }),
|
||||
forConfigurationName: configuration
|
||||
)
|
||||
}
|
||||
self.cachedRawModel = rawModel
|
||||
return rawModel
|
||||
}
|
||||
self.cachedRawModel = rawModel
|
||||
return rawModel
|
||||
}
|
||||
|
||||
|
||||
@@ -244,28 +253,33 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
private let allEntities: Set<DynamicEntity>
|
||||
|
||||
private var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:]
|
||||
private var customGettersSettersByEntity: [DynamicEntity: [KeyPath: CoreStoreManagedObject.CustomGetterSetter]] = [:]
|
||||
private weak var cachedRawModel: NSManagedObjectModel?
|
||||
|
||||
private func entityDescription(for entity: DynamicEntity, initializer: (DynamicEntity) -> NSEntityDescription) -> NSEntityDescription {
|
||||
private func entityDescription(for entity: DynamicEntity, initializer: (DynamicEntity, ModelVersion) -> (entity: NSEntityDescription, customGetterSetterByKeyPaths: [KeyPath: CoreStoreManagedObject.CustomGetterSetter])) -> (entity: NSEntityDescription, customGetterSetterByKeyPaths: [KeyPath: CoreStoreManagedObject.CustomGetterSetter]) {
|
||||
|
||||
if let cachedEntityDescription = self.entityDescriptionsByEntity[entity] {
|
||||
|
||||
return cachedEntityDescription
|
||||
return (cachedEntityDescription, self.customGettersSettersByEntity[entity] ?? [:])
|
||||
}
|
||||
let entityDescription = withoutActuallyEscaping(initializer, do: { $0(entity) })
|
||||
let modelVersion = self.modelVersion
|
||||
let (entityDescription, customGetterSetterByKeyPaths) = withoutActuallyEscaping(initializer, do: { $0(entity, modelVersion) })
|
||||
self.entityDescriptionsByEntity[entity] = entityDescription
|
||||
return entityDescription
|
||||
self.customGettersSettersByEntity[entity] = customGetterSetterByKeyPaths
|
||||
return (entityDescription, customGetterSetterByKeyPaths)
|
||||
}
|
||||
|
||||
private static func firstPassCreateEntityDescription(from entity: DynamicEntity) -> NSEntityDescription {
|
||||
private static func firstPassCreateEntityDescription(from entity: DynamicEntity, in modelVersion: ModelVersion) -> (entity: NSEntityDescription, customGetterSetterByKeyPaths: [KeyPath: CoreStoreManagedObject.CustomGetterSetter]) {
|
||||
|
||||
let entityDescription = NSEntityDescription()
|
||||
entityDescription.coreStoreEntity = entity
|
||||
entityDescription.name = entity.entityName
|
||||
entityDescription.isAbstract = entity.isAbstract
|
||||
entityDescription.versionHashModifier = entity.versionHashModifier
|
||||
entityDescription.managedObjectClassName = NSStringFromClass(NSManagedObject.self)
|
||||
entityDescription.managedObjectClassName = CoreStoreManagedObject.cs_subclassName(for: entity, in: modelVersion)
|
||||
|
||||
var keyPathsByAffectedKeyPaths: [KeyPath: Set<KeyPath>] = [:]
|
||||
var customGetterSetterByKeyPaths: [KeyPath: CoreStoreManagedObject.CustomGetterSetter] = [:]
|
||||
func createProperties(for type: CoreStoreObject.Type) -> [NSPropertyDescription] {
|
||||
|
||||
var propertyDescriptions: [NSPropertyDescription] = []
|
||||
@@ -279,11 +293,13 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
description.attributeType = type(of: attribute).attributeType
|
||||
description.isOptional = attribute.isOptional
|
||||
description.isIndexed = attribute.isIndexed
|
||||
description.defaultValue = attribute.defaultValue
|
||||
description.defaultValue = attribute.defaultValue()
|
||||
description.isTransient = attribute.isTransient
|
||||
description.versionHashModifier = attribute.versionHashModifier
|
||||
description.renamingIdentifier = attribute.renamingIdentifier
|
||||
propertyDescriptions.append(description)
|
||||
keyPathsByAffectedKeyPaths[attribute.keyPath] = attribute.affectedByKeyPaths()
|
||||
customGetterSetterByKeyPaths[attribute.keyPath] = (attribute.getter, attribute.setter)
|
||||
|
||||
case let relationship as RelationshipProtocol:
|
||||
let description = NSRelationshipDescription()
|
||||
@@ -295,6 +311,7 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
description.versionHashModifier = relationship.versionHashModifier
|
||||
description.renamingIdentifier = relationship.renamingIdentifier
|
||||
propertyDescriptions.append(description)
|
||||
keyPathsByAffectedKeyPaths[relationship.keyPath] = relationship.affectedByKeyPaths()
|
||||
|
||||
default:
|
||||
continue
|
||||
@@ -302,9 +319,9 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
}
|
||||
return propertyDescriptions
|
||||
}
|
||||
|
||||
entityDescription.properties = createProperties(for: entity.type as! CoreStoreObject.Type)
|
||||
return entityDescription
|
||||
entityDescription.keyPathsByAffectedKeyPaths = keyPathsByAffectedKeyPaths
|
||||
return (entityDescription, customGetterSetterByKeyPaths)
|
||||
}
|
||||
|
||||
private static func secondPassConnectRelationshipAttributes(for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription]) {
|
||||
@@ -425,4 +442,112 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private static func fourthPassSynthesizeManagedObjectClasses(for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription], allCustomGettersSetters: [DynamicEntity: [KeyPath: CoreStoreManagedObject.CustomGetterSetter]]) {
|
||||
|
||||
func createManagedObjectSubclass(for entityDescription: NSEntityDescription, customGetterSetterByKeyPaths: [KeyPath: CoreStoreManagedObject.CustomGetterSetter]?) {
|
||||
|
||||
let superEntity = entityDescription.superentity
|
||||
let className = entityDescription.managedObjectClassName!
|
||||
guard case nil = NSClassFromString(className) as! CoreStoreManagedObject.Type? else {
|
||||
|
||||
return
|
||||
}
|
||||
if let superEntity = superEntity {
|
||||
|
||||
createManagedObjectSubclass(
|
||||
for: superEntity,
|
||||
customGetterSetterByKeyPaths: superEntity.coreStoreEntity.flatMap({ allCustomGettersSetters[$0] })
|
||||
)
|
||||
}
|
||||
let superClass = cs_lazy { () -> CoreStoreManagedObject.Type in
|
||||
|
||||
if let superClassName = superEntity?.managedObjectClassName,
|
||||
let superClass = NSClassFromString(superClassName) {
|
||||
|
||||
return superClass as! CoreStoreManagedObject.Type
|
||||
}
|
||||
return CoreStoreManagedObject.self
|
||||
}
|
||||
let managedObjectClass: AnyClass = className.withCString {
|
||||
|
||||
return objc_allocateClassPair(superClass, $0, 0)!
|
||||
}
|
||||
defer {
|
||||
|
||||
objc_registerClassPair(managedObjectClass)
|
||||
}
|
||||
|
||||
func capitalize(_ string: String) -> String {
|
||||
|
||||
return string.replacingCharacters(
|
||||
in: Range(uncheckedBounds: (string.startIndex, string.index(after: string.startIndex))),
|
||||
with: String(string[string.startIndex]).uppercased()
|
||||
)
|
||||
}
|
||||
for (attributeName, customGetterSetters) in (customGetterSetterByKeyPaths ?? [:])
|
||||
where customGetterSetters.getter != nil || customGetterSetters.setter != nil {
|
||||
|
||||
if let getter = customGetterSetters.getter {
|
||||
|
||||
let getterName = "\(attributeName)"
|
||||
guard class_addMethod(
|
||||
managedObjectClass,
|
||||
NSSelectorFromString(getterName),
|
||||
imp_implementationWithBlock(getter),
|
||||
"@@:") else {
|
||||
|
||||
CoreStore.abort("Could not dynamically add getter method \"\(getterName)\" to class \(cs_typeName(managedObjectClass))")
|
||||
}
|
||||
}
|
||||
if let setter = customGetterSetters.setter {
|
||||
|
||||
let setterName = "set\(capitalize(attributeName)):"
|
||||
guard class_addMethod(
|
||||
managedObjectClass,
|
||||
NSSelectorFromString(setterName),
|
||||
imp_implementationWithBlock(setter),
|
||||
"v@:@") else {
|
||||
|
||||
CoreStore.abort("Could not dynamically add setter method \"\(setterName)\" to class \(cs_typeName(managedObjectClass))")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let newSelector = NSSelectorFromString("cs_keyPathsForValuesAffectingValueForKey:")
|
||||
let keyPathsByAffectedKeyPaths = entityDescription.keyPathsByAffectedKeyPaths
|
||||
let keyPathsForValuesAffectingValue: @convention(block) (Any, String) -> Set<String> = { (instance, keyPath) in
|
||||
|
||||
if let keyPaths = keyPathsByAffectedKeyPaths[keyPath] {
|
||||
|
||||
return keyPaths
|
||||
}
|
||||
return []
|
||||
}
|
||||
let origSelector = #selector(NSManagedObject.keyPathsForValuesAffectingValue(forKey:))
|
||||
|
||||
let metaClass: AnyClass = object_getClass(managedObjectClass)!
|
||||
let origMethod = class_getClassMethod(managedObjectClass, origSelector)
|
||||
|
||||
let origImp = method_getImplementation(origMethod)
|
||||
let newImp = imp_implementationWithBlock(keyPathsForValuesAffectingValue)
|
||||
|
||||
if class_addMethod(metaClass, origSelector, newImp, method_getTypeEncoding(origMethod)) {
|
||||
|
||||
class_replaceMethod(metaClass, newSelector, origImp, method_getTypeEncoding(origMethod))
|
||||
}
|
||||
else {
|
||||
|
||||
let newMethod = class_getClassMethod(managedObjectClass, newSelector)
|
||||
method_exchangeImplementations(origMethod, newMethod)
|
||||
}
|
||||
}
|
||||
for (dynamicEntity, entityDescription) in entityDescriptionsByEntity {
|
||||
|
||||
createManagedObjectSubclass(
|
||||
for: entityDescription,
|
||||
customGetterSetterByKeyPaths: allCustomGettersSetters[dynamicEntity]
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import Foundation
|
||||
/**
|
||||
A `SchemaMappingProvider` that accepts custom mappings for some entities. Mappings of entities with no `CustomMapping` provided will be automatically calculated if possible.
|
||||
*/
|
||||
open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
|
||||
/**
|
||||
The source model version for the mapping.
|
||||
@@ -352,7 +352,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
)
|
||||
func expression(forSource sourceEntity: NSEntityDescription) -> NSExpression {
|
||||
|
||||
return NSExpression(format: "FETCH(FUNCTION($\(NSMigrationManagerKey), \"fetchRequestForSourceEntityNamed:predicateString:\" , \"\(sourceEntity.name!)\", \"\(NSPredicate(value: true))\"), $\(NSMigrationManagerKey).\(#keyPath(NSMigrationManager.sourceContext)), \(false))")
|
||||
return NSExpression(format: "FETCH(FUNCTION($\(NSMigrationManagerKey), \"fetchRequestForSourceEntityNamed:predicateString:\" , \"\(sourceEntity.name!)\", \"\(NSPredicate(value: true))\"), FUNCTION($\(NSMigrationManagerKey), \"\(#selector(getter: NSMigrationManager.sourceContext))\"), \(false))")
|
||||
}
|
||||
|
||||
let sourceEntitiesByName = sourceModel.entitiesByName
|
||||
@@ -427,22 +427,25 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
let destinationAttribute = destination.attribute
|
||||
let propertyMapping = NSPropertyMapping()
|
||||
propertyMapping.name = destinationAttribute.name
|
||||
propertyMapping.valueExpression = NSExpression(format: "$\(NSMigrationSourceObjectKey).\(sourceAttribute.name)")
|
||||
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationSourceObjectKey), \"\(#selector(NSManagedObject.value(forKey:)))\", \"\(sourceAttribute.name)\")")
|
||||
attributeMappings.append(propertyMapping)
|
||||
}
|
||||
return attributeMappings
|
||||
}
|
||||
let entityMappingName = entityMapping.name!
|
||||
entityMapping.relationshipMappings = autoreleasepool { () -> [NSPropertyMapping] in
|
||||
|
||||
let sourceRelationships = sourceEntity.cs_resolvedRelationshipRenamingIdentities()
|
||||
let destinationRelationships = destinationEntity.cs_resolvedRelationshipRenamingIdentities()
|
||||
var relationshipMappings: [NSPropertyMapping] = []
|
||||
for (_, destination) in destinationRelationships {
|
||||
for (renamingIdentifier, destination) in destinationRelationships {
|
||||
|
||||
let sourceRelationship = sourceRelationships[renamingIdentifier]!.relationship
|
||||
let destinationRelationship = destination.relationship
|
||||
let sourceRelationshipName = sourceRelationship.name
|
||||
|
||||
let propertyMapping = NSPropertyMapping()
|
||||
propertyMapping.name = destinationRelationship.name
|
||||
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"\(#selector(NSMigrationManager.destinationInstances(forEntityMappingName:sourceInstances:)))\" , \"\(entityMappingName)\", $\(NSMigrationSourceObjectKey))[0]")
|
||||
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"destinationInstancesForSourceRelationshipNamed:sourceInstances:\", \"\(sourceRelationshipName)\", FUNCTION($\(NSMigrationSourceObjectKey), \"\(#selector(NSManagedObject.value(forKey:)))\", \"\(sourceRelationshipName)\"))")
|
||||
relationshipMappings.append(propertyMapping)
|
||||
}
|
||||
return relationshipMappings
|
||||
@@ -483,17 +486,24 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
}
|
||||
userInfo[CustomEntityMigrationPolicy.UserInfoKey.sourceAttributesByDestinationKey] = sourceAttributesByDestinationKey
|
||||
}
|
||||
let entityMappingName = entityMapping.name!
|
||||
entityMapping.relationshipMappings = autoreleasepool { () -> [NSPropertyMapping] in
|
||||
|
||||
let sourceRelationships = sourceEntity.cs_resolvedRelationshipRenamingIdentities()
|
||||
let destinationRelationships = destinationEntity.cs_resolvedRelationshipRenamingIdentities()
|
||||
let transformedRenamingIdentifiers = Set(destinationRelationships.keys)
|
||||
.intersection(sourceRelationships.keys)
|
||||
|
||||
var relationshipMappings: [NSPropertyMapping] = []
|
||||
for (_, destination) in destinationRelationships {
|
||||
|
||||
let destinationRelationship = destination.relationship
|
||||
for renamingIdentifier in transformedRenamingIdentifiers {
|
||||
|
||||
let sourceRelationship = sourceRelationships[renamingIdentifier]!.relationship
|
||||
let destinationRelationship = destinationRelationships[renamingIdentifier]!.relationship
|
||||
let sourceRelationshipName = sourceRelationship.name
|
||||
let destinationRelationshipName = destinationRelationship.name
|
||||
|
||||
let propertyMapping = NSPropertyMapping()
|
||||
propertyMapping.name = destinationRelationship.name
|
||||
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"\(#selector(NSMigrationManager.destinationInstances(forEntityMappingName:sourceInstances:)))\" , \"\(entityMappingName)\", $\(NSMigrationSourceObjectKey))[0]")
|
||||
propertyMapping.name = destinationRelationshipName
|
||||
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"destinationInstancesForSourceRelationshipNamed:sourceInstances:\", \"\(sourceRelationshipName)\", FUNCTION($\(NSMigrationSourceObjectKey), \"\(#selector(NSManagedObject.value(forKey:)))\", \"\(sourceRelationshipName)\"))")
|
||||
relationshipMappings.append(propertyMapping)
|
||||
}
|
||||
return relationshipMappings
|
||||
@@ -545,11 +555,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
)
|
||||
if let dInstance = destinationObject?.rawObject {
|
||||
|
||||
manager.associate(
|
||||
sourceInstance: sInstance,
|
||||
withDestinationInstance: dInstance,
|
||||
for: mapping
|
||||
)
|
||||
manager.associate(sourceInstance: sInstance, withDestinationInstance: dInstance, for: mapping)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -670,77 +676,76 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
allMappedSourceKeys[sourceEntity] = destinationEntity
|
||||
allMappedDestinationKeys[destinationEntity] = sourceEntity
|
||||
}
|
||||
}
|
||||
for renamingIdentifier in transformedRenamingIdentifiers {
|
||||
|
||||
for renamingIdentifier in transformedRenamingIdentifiers {
|
||||
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let sourceEntityName = sourceEntity.name!
|
||||
let destinationEntityName = destinationEntity.name!
|
||||
switch (allMappedSourceKeys[sourceEntityName], allMappedDestinationKeys[destinationEntityName]) {
|
||||
|
||||
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let sourceEntityName = sourceEntity.name!
|
||||
let destinationEntityName = destinationEntity.name!
|
||||
switch (allMappedSourceKeys[sourceEntityName], allMappedDestinationKeys[destinationEntityName]) {
|
||||
case (nil, nil):
|
||||
if sourceEntity.versionHash == destinationEntity.versionHash {
|
||||
|
||||
case (nil, nil):
|
||||
if sourceEntity.versionHash == destinationEntity.versionHash {
|
||||
|
||||
copyMappings.insert(
|
||||
.copyEntity(
|
||||
sourceEntity: sourceEntityName,
|
||||
destinationEntity: destinationEntityName
|
||||
)
|
||||
copyMappings.insert(
|
||||
.copyEntity(
|
||||
sourceEntity: sourceEntityName,
|
||||
destinationEntity: destinationEntityName
|
||||
)
|
||||
}
|
||||
else {
|
||||
|
||||
transformMappings.insert(
|
||||
.transformEntity(
|
||||
sourceEntity: sourceEntityName,
|
||||
destinationEntity: destinationEntityName,
|
||||
transformer: CustomMapping.inferredTransformation
|
||||
)
|
||||
)
|
||||
}
|
||||
else {
|
||||
|
||||
transformMappings.insert(
|
||||
.transformEntity(
|
||||
sourceEntity: sourceEntityName,
|
||||
destinationEntity: destinationEntityName,
|
||||
transformer: CustomMapping.inferredTransformation
|
||||
)
|
||||
}
|
||||
allMappedSourceKeys[sourceEntityName] = destinationEntityName
|
||||
allMappedDestinationKeys[destinationEntityName] = sourceEntityName
|
||||
|
||||
case (""?, nil):
|
||||
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
|
||||
allMappedDestinationKeys[destinationEntityName] = ""
|
||||
|
||||
case (nil, ""?):
|
||||
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
|
||||
allMappedSourceKeys[sourceEntityName] = ""
|
||||
|
||||
default:
|
||||
continue
|
||||
)
|
||||
}
|
||||
}
|
||||
for renamingIdentifier in removedRenamingIdentifiers {
|
||||
allMappedSourceKeys[sourceEntityName] = destinationEntityName
|
||||
allMappedDestinationKeys[destinationEntityName] = sourceEntityName
|
||||
|
||||
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let sourceEntityName = sourceEntity.name!
|
||||
switch allMappedSourceKeys[sourceEntityName] {
|
||||
|
||||
case nil:
|
||||
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
|
||||
allMappedSourceKeys[sourceEntityName] = ""
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
for renamingIdentifier in addedRenamingIdentifiers {
|
||||
case (""?, nil):
|
||||
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
|
||||
allMappedDestinationKeys[destinationEntityName] = ""
|
||||
|
||||
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let destinationEntityName = destinationEntity.name!
|
||||
switch allMappedDestinationKeys[destinationEntityName] {
|
||||
|
||||
case nil:
|
||||
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
|
||||
allMappedDestinationKeys[destinationEntityName] = ""
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
case (nil, ""?):
|
||||
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
|
||||
allMappedSourceKeys[sourceEntityName] = ""
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
for renamingIdentifier in removedRenamingIdentifiers {
|
||||
|
||||
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let sourceEntityName = sourceEntity.name!
|
||||
switch allMappedSourceKeys[sourceEntityName] {
|
||||
|
||||
case nil:
|
||||
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
|
||||
allMappedSourceKeys[sourceEntityName] = ""
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
for renamingIdentifier in addedRenamingIdentifiers {
|
||||
|
||||
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let destinationEntityName = destinationEntity.name!
|
||||
switch allMappedDestinationKeys[destinationEntityName] {
|
||||
|
||||
case nil:
|
||||
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
|
||||
allMappedDestinationKeys[destinationEntityName] = ""
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
return (deleteMappings, insertMappings, copyMappings, transformMappings)
|
||||
|
||||
@@ -63,7 +63,7 @@ public extension DataStack {
|
||||
|
||||
defer {
|
||||
|
||||
withExtendedLifetime(transaction, {})
|
||||
withExtendedLifetime((self, transaction), {})
|
||||
}
|
||||
let userInfo: T
|
||||
do {
|
||||
@@ -112,7 +112,7 @@ public extension DataStack {
|
||||
|
||||
defer {
|
||||
|
||||
withExtendedLifetime(transaction, {})
|
||||
withExtendedLifetime((self, transaction), {})
|
||||
}
|
||||
let userInfo: T
|
||||
do {
|
||||
|
||||
@@ -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`.
|
||||
|
||||
- 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 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(
|
||||
schemaHistory: SchemaHistory(
|
||||
XcodeDataModelSchema.from(
|
||||
modelName: modelName,
|
||||
modelName: xcodeModelName,
|
||||
bundle: bundle,
|
||||
migrationChain: migrationChain
|
||||
),
|
||||
@@ -613,14 +613,25 @@ public final class DataStack: Equatable {
|
||||
|
||||
// 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) {
|
||||
|
||||
let modelVersion = migrationChain.leafVersions.first!
|
||||
self.init(
|
||||
schemaHistory: SchemaHistory(
|
||||
allSchema: [
|
||||
LegacyXcodeDataModelSchema(
|
||||
UnsafeDataModelSchema(
|
||||
modelName: modelVersion,
|
||||
model: model
|
||||
)
|
||||
|
||||
@@ -48,6 +48,11 @@ public protocol DynamicObject: class {
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@@ -86,6 +91,11 @@ extension NSManagedObject: DynamicObject {
|
||||
return object.isKind(of: self)
|
||||
}
|
||||
|
||||
public func cs_id() -> NSManagedObjectID {
|
||||
|
||||
return self.objectID
|
||||
}
|
||||
|
||||
public func cs_toRaw() -> NSManagedObject {
|
||||
|
||||
return self
|
||||
@@ -135,6 +145,11 @@ extension CoreStoreObject {
|
||||
return (self as AnyClass).isSubclass(of: type as AnyClass)
|
||||
}
|
||||
|
||||
public func cs_id() -> NSManagedObjectID {
|
||||
|
||||
return self.rawObject!.objectID
|
||||
}
|
||||
|
||||
public func cs_toRaw() -> NSManagedObject {
|
||||
|
||||
return self.rawObject!
|
||||
|
||||
@@ -31,6 +31,12 @@ import Foundation
|
||||
|
||||
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 {
|
||||
|
||||
let model = self.rawModel()
|
||||
@@ -147,8 +153,7 @@ public extension DynamicSchema {
|
||||
}
|
||||
case .dateAttributeType:
|
||||
valueType = Date.self
|
||||
if let defaultValue = (attribute.defaultValue as! Date.ImportableNativeType?).flatMap(Date.cs_fromImportableNativeType),
|
||||
defaultValue != Date.cs_emptyValue() {
|
||||
if let defaultValue = (attribute.defaultValue as! Date.ImportableNativeType?).flatMap(Date.cs_fromImportableNativeType) {
|
||||
|
||||
defaultString = ", default: Date(timeIntervalSinceReferenceDate: \(defaultValue.timeIntervalSinceReferenceDate))"
|
||||
}
|
||||
@@ -188,9 +193,11 @@ public extension DynamicSchema {
|
||||
let indexedString = attribute.isIndexed ? ", isIndexed: true" : ""
|
||||
let transientString = attribute.isTransient ? ", isTransient: true" : ""
|
||||
// TODO: escape strings
|
||||
let versionHashModifierString = attribute.versionHashModifier.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
||||
let versionHashModifierString = attribute.versionHashModifier
|
||||
.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
||||
// 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")
|
||||
}
|
||||
}
|
||||
@@ -255,8 +262,10 @@ public extension DynamicSchema {
|
||||
fatalError("Unsupported delete rule \((relationship.deleteRule)) for relationship \"\(relationshipQualifier)\"")
|
||||
}
|
||||
}
|
||||
let versionHashModifierString = relationship.versionHashModifier.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
||||
let renamingIdentifierString = relationship.renamingIdentifier.flatMap({ ", renamingIdentifier: \"\($0)\"" }) ?? ""
|
||||
let versionHashModifierString = relationship.versionHashModifier
|
||||
.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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
- `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.
|
||||
*/
|
||||
public protocol DynamicSchema {
|
||||
|
||||
@@ -54,7 +54,7 @@ internal struct EntityIdentifier: Hashable {
|
||||
internal init(_ type: CoreStoreObject.Type) {
|
||||
|
||||
self.category = .coreStore
|
||||
self.interfacedClassName = String(reflecting: type)
|
||||
self.interfacedClassName = NSStringFromClass(type)
|
||||
}
|
||||
|
||||
internal init(_ type: DynamicObject.Type) {
|
||||
|
||||
@@ -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 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 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`.
|
||||
*/
|
||||
public required init?(ubiquitousContentName: String, ubiquitousContentTransactionLogsSubdirectory: String, ubiquitousContainerID: String? = nil, ubiquitousPeerToken: String? = nil, configuration: ModelConfiguration = nil, cloudStorageOptions: CloudStorageOptions = nil) {
|
||||
|
||||
@@ -64,12 +64,6 @@ public protocol ImportableAttributeType: QueryableAttributeType {
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@@ -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
|
||||
|
||||
extension Bool: ImportableAttributeType {
|
||||
extension Bool: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Bool? {
|
||||
|
||||
@@ -107,21 +114,26 @@ extension Bool: ImportableAttributeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
|
||||
|
||||
// MARK: EmptyableAttributeType
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Bool {
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - CGFloat
|
||||
|
||||
extension CGFloat: ImportableAttributeType {
|
||||
extension CGFloat: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> CGFloat {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> CGFloat? {
|
||||
|
||||
@@ -133,21 +145,26 @@ extension CGFloat: ImportableAttributeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
|
||||
|
||||
// MARK: EmptyableAttributeType
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> CGFloat {
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Data
|
||||
|
||||
extension Data: ImportableAttributeType {
|
||||
extension Data: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSData
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Data {
|
||||
|
||||
return Data()
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Data? {
|
||||
|
||||
@@ -159,6 +176,15 @@ extension Data: ImportableAttributeType {
|
||||
|
||||
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 {
|
||||
|
||||
public typealias ImportableNativeType = NSDate
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Date {
|
||||
|
||||
return Date(timeIntervalSinceReferenceDate: 0)
|
||||
}
|
||||
public typealias ImportableNativeType = NSDate
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Date? {
|
||||
@@ -190,16 +212,12 @@ extension Date: ImportableAttributeType {
|
||||
|
||||
// MARK: - Double
|
||||
|
||||
extension Double: ImportableAttributeType {
|
||||
extension Double: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Double {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Double? {
|
||||
|
||||
@@ -211,21 +229,26 @@ extension Double: ImportableAttributeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
|
||||
|
||||
// MARK: EmptyableAttributeType
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Double {
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Float
|
||||
|
||||
extension Float: ImportableAttributeType {
|
||||
extension Float: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Float {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Float? {
|
||||
|
||||
@@ -237,21 +260,26 @@ extension Float: ImportableAttributeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
|
||||
|
||||
// MARK: EmptyableAttributeType
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Float {
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Int
|
||||
|
||||
extension Int: ImportableAttributeType {
|
||||
extension Int: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int? {
|
||||
|
||||
@@ -263,21 +291,26 @@ extension Int: ImportableAttributeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
|
||||
|
||||
// MARK: EmptyableAttributeType
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int {
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Int8
|
||||
|
||||
extension Int8: ImportableAttributeType {
|
||||
extension Int8: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int8 {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int8? {
|
||||
|
||||
@@ -289,21 +322,26 @@ extension Int8: ImportableAttributeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
|
||||
|
||||
// MARK: EmptyableAttributeType
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int8 {
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Int16
|
||||
|
||||
extension Int16: ImportableAttributeType {
|
||||
extension Int16: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int16 {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int16? {
|
||||
|
||||
@@ -315,21 +353,26 @@ extension Int16: ImportableAttributeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
|
||||
|
||||
// MARK: EmptyableAttributeType
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int16 {
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Int32
|
||||
|
||||
extension Int32: ImportableAttributeType {
|
||||
extension Int32: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int32 {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int32? {
|
||||
|
||||
@@ -341,21 +384,26 @@ extension Int32: ImportableAttributeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
|
||||
|
||||
// MARK: EmptyableAttributeType
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int32 {
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Int64
|
||||
|
||||
extension Int64: ImportableAttributeType {
|
||||
extension Int64: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int64 {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int64? {
|
||||
|
||||
@@ -367,21 +415,26 @@ extension Int64: ImportableAttributeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
|
||||
|
||||
// MARK: EmptyableAttributeType
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int64 {
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - NSData
|
||||
|
||||
extension NSData: ImportableAttributeType {
|
||||
extension NSData: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSData
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
return self.init()
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
@@ -393,6 +446,15 @@ extension NSData: ImportableAttributeType {
|
||||
|
||||
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 {
|
||||
|
||||
public typealias ImportableNativeType = NSDate
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
return self.init(timeIntervalSinceReferenceDate: 0)
|
||||
}
|
||||
public typealias ImportableNativeType = NSDate
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
@@ -424,16 +482,12 @@ extension NSDate: ImportableAttributeType {
|
||||
|
||||
// MARK: - NSNumber
|
||||
|
||||
extension NSNumber: ImportableAttributeType {
|
||||
extension NSNumber: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
return self.init()
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
@@ -445,21 +499,26 @@ extension NSNumber: ImportableAttributeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
|
||||
|
||||
// MARK: EmptyableAttributeType
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
return self.init()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - NSString
|
||||
|
||||
extension NSString: ImportableAttributeType {
|
||||
extension NSString: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSString
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
return self.init()
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
@@ -471,6 +530,15 @@ extension NSString: ImportableAttributeType {
|
||||
|
||||
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 {
|
||||
|
||||
public typealias ImportableNativeType = NSString
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
return self.init(string: "")!
|
||||
}
|
||||
public typealias ImportableNativeType = NSString
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
@@ -504,16 +568,9 @@ extension NSURL: ImportableAttributeType {
|
||||
|
||||
extension NSUUID: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSString
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
enum Static {
|
||||
|
||||
static var zero = Array<UInt8>(repeating: 0, count: 16)
|
||||
}
|
||||
return self.init(uuidBytes: &Static.zero)
|
||||
}
|
||||
public typealias ImportableNativeType = NSString
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
@@ -531,16 +588,12 @@ extension NSUUID: ImportableAttributeType {
|
||||
|
||||
// MARK: - String
|
||||
|
||||
extension String: ImportableAttributeType {
|
||||
extension String: ImportableAttributeType, EmptyableAttributeType {
|
||||
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public typealias ImportableNativeType = NSString
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> String {
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> String? {
|
||||
|
||||
@@ -552,6 +605,15 @@ extension String: ImportableAttributeType {
|
||||
|
||||
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 {
|
||||
|
||||
public typealias ImportableNativeType = NSString
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public static func cs_emptyValue() -> URL {
|
||||
|
||||
enum Static {
|
||||
|
||||
static let empty = URL(string: "")!
|
||||
}
|
||||
return Static.empty
|
||||
}
|
||||
public typealias ImportableNativeType = NSString
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> URL? {
|
||||
@@ -588,20 +643,9 @@ extension URL: ImportableAttributeType {
|
||||
|
||||
extension UUID: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSString
|
||||
// MARK: ImportableAttributeType
|
||||
|
||||
public static func cs_emptyValue() -> UUID {
|
||||
|
||||
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
|
||||
}
|
||||
public typealias ImportableNativeType = NSString
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> UUID? {
|
||||
@@ -623,11 +667,6 @@ extension RawRepresentable where RawValue: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = RawValue.ImportableNativeType
|
||||
|
||||
public static func cs_emptyValue() -> Self {
|
||||
|
||||
return self.init(rawValue: RawValue.cs_emptyValue())!
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import Foundation
|
||||
/**
|
||||
A `SchemaMappingProvider` that tries to infer model migration between two `DynamicSchema` versions by searching all `xcmappingmodel`s from `Bundle.allBundles` or by relying on lightweight migration if possible. Throws an error if lightweight migration is impossible for the two `DynamicSchema`. This mapping is automatically used as a fallback mapping provider, even if no mapping providers are explicitly declared in the `StorageInterface`.
|
||||
*/
|
||||
final class InferredSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
public final class InferredSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.0.0</string>
|
||||
<string>4.0.5</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
@@ -704,13 +704,13 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
guard let `self` = self,
|
||||
let userInfo = note.userInfo,
|
||||
let object = userInfo[String(describing: NSManagedObject.self)] as? ObjectType else {
|
||||
let rawObject = userInfo[String(describing: NSManagedObject.self)] as? NSManagedObject else {
|
||||
|
||||
return
|
||||
}
|
||||
callback(
|
||||
self,
|
||||
object,
|
||||
ObjectType.cs_fromRaw(object: rawObject),
|
||||
userInfo[String(describing: IndexPath.self)] as? IndexPath,
|
||||
userInfo["\(String(describing: IndexPath.self)).New"] as? IndexPath
|
||||
)
|
||||
|
||||
@@ -56,8 +56,7 @@ public protocol ListObserver: class {
|
||||
func listMonitorWillChange(_ monitor: ListMonitor<ListEntityType>)
|
||||
|
||||
/**
|
||||
Handles processing right after a change to the observed list occurs. (Optional)
|
||||
The default implementation does nothing.
|
||||
Handles processing right after a change to the observed list occurs. (Required)
|
||||
|
||||
- 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)
|
||||
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
|
||||
*/
|
||||
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)
|
||||
The default implementation does nothing.
|
||||
After the `ListMonitor`'s `refetch(...)` method is called, this method is broadcast after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes. (Required)
|
||||
|
||||
- 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
|
||||
*/
|
||||
func listMonitorDidRefetch(_ monitor: ListMonitor<ListEntityType>)
|
||||
@@ -89,11 +87,7 @@ public extension ListObserver {
|
||||
|
||||
public func listMonitorWillChange(_ monitor: ListMonitor<ListEntityType>) { }
|
||||
|
||||
public func listMonitorDidChange(_ monitor: ListMonitor<ListEntityType>) { }
|
||||
|
||||
public func listMonitorWillRefetch(_ monitor: ListMonitor<ListEntityType>) { }
|
||||
|
||||
public func listMonitorDidRefetch(_ monitor: ListMonitor<ListEntityType>) { }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -54,17 +54,65 @@ internal extension NSEntityDescription {
|
||||
|
||||
if let newValue = newValue {
|
||||
|
||||
var userInfo: [AnyHashable : Any] = [
|
||||
UserInfoKey.CoreStoreManagedObjectTypeName: NSStringFromClass(newValue.type),
|
||||
UserInfoKey.CoreStoreManagedObjectEntityName: newValue.entityName,
|
||||
UserInfoKey.CoreStoreManagedObjectIsAbstract: newValue.isAbstract
|
||||
]
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectVersionHashModifier] = newValue.versionHashModifier
|
||||
self.userInfo = userInfo
|
||||
cs_setUserInfo { (userInfo) in
|
||||
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectTypeName] = NSStringFromClass(newValue.type)
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectEntityName] = newValue.entityName
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectIsAbstract] = newValue.isAbstract
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectVersionHashModifier] = newValue.versionHashModifier
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
self.userInfo = [:]
|
||||
cs_setUserInfo { (userInfo) in
|
||||
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectTypeName] = nil
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectEntityName] = nil
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectIsAbstract] = nil
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectVersionHashModifier] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal var keyPathsByAffectedKeyPaths: [KeyPath: Set<KeyPath>] {
|
||||
|
||||
get {
|
||||
|
||||
if let userInfo = self.userInfo,
|
||||
let value = userInfo[UserInfoKey.CoreStoreManagedObjectKeyPathsByAffectedKeyPaths] {
|
||||
|
||||
return value as! [KeyPath: Set<KeyPath>]
|
||||
}
|
||||
return [:]
|
||||
}
|
||||
set {
|
||||
|
||||
cs_setUserInfo { (userInfo) in
|
||||
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectKeyPathsByAffectedKeyPaths] = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal var customGetterSetterByKeyPaths: [KeyPath: CoreStoreManagedObject.CustomGetterSetter] {
|
||||
|
||||
get {
|
||||
|
||||
if let userInfo = self.userInfo,
|
||||
let value = userInfo[UserInfoKey.CoreStoreManagedObjectCustomGetterSetterByKeyPaths] {
|
||||
|
||||
return value as! [KeyPath: CoreStoreManagedObject.CustomGetterSetter]
|
||||
}
|
||||
return [:]
|
||||
}
|
||||
set {
|
||||
|
||||
cs_setUserInfo { (userInfo) in
|
||||
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectCustomGetterSetterByKeyPaths] = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,11 +122,22 @@ internal extension NSEntityDescription {
|
||||
|
||||
// MARK: - UserInfoKey
|
||||
|
||||
fileprivate enum UserInfoKey {
|
||||
private enum UserInfoKey {
|
||||
|
||||
fileprivate static let CoreStoreManagedObjectTypeName = "CoreStoreManagedObjectTypeName"
|
||||
fileprivate static let CoreStoreManagedObjectEntityName = "CoreStoreManagedObjectEntityName"
|
||||
fileprivate static let CoreStoreManagedObjectIsAbstract = "CoreStoreManagedObjectIsAbstract"
|
||||
fileprivate static let CoreStoreManagedObjectVersionHashModifier = "CoreStoreManagedObjectVersionHashModifier"
|
||||
|
||||
fileprivate static let CoreStoreManagedObjectKeyPathsByAffectedKeyPaths = "CoreStoreManagedObjectKeyPathsByAffectedKeyPaths"
|
||||
fileprivate static let CoreStoreManagedObjectCustomGetterSetterByKeyPaths = "CoreStoreManagedObjectCustomGetterSetterByKeyPaths"
|
||||
|
||||
}
|
||||
|
||||
private func cs_setUserInfo(_ closure: (_ userInfo: inout [AnyHashable: Any]) -> Void) {
|
||||
|
||||
var userInfo = self.userInfo ?? [:]
|
||||
closure(&userInfo)
|
||||
self.userInfo = userInfo
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ public extension UnsafeDataTransaction {
|
||||
// MARK: - Private
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
fileprivate func createFRC<T: NSManagedObject>(fromContext context: NSManagedObjectContext, from: From<T>? = nil, sectionBy: SectionBy? = nil, fetchClauses: [FetchClause]) -> NSFetchedResultsController<T> {
|
||||
fileprivate func createFRC<T: NSManagedObject>(fromContext context: NSManagedObjectContext, from: From<T>, sectionBy: SectionBy? = nil, fetchClauses: [FetchClause]) -> NSFetchedResultsController<T> {
|
||||
|
||||
let controller = CoreStoreFetchedResultsController(
|
||||
context: context,
|
||||
|
||||
@@ -68,12 +68,12 @@ public extension CSUnsafeDataTransaction {
|
||||
// MARK: - Private
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
fileprivate func createFRC(fromContext context: NSManagedObjectContext, from: CSFrom? = nil, sectionBy: CSSectionBy?, fetchClauses: [CSFetchClause]) -> NSFetchedResultsController<NSManagedObject> {
|
||||
fileprivate func createFRC(fromContext context: NSManagedObjectContext, from: CSFrom, sectionBy: CSSectionBy?, fetchClauses: [CSFetchClause]) -> NSFetchedResultsController<NSManagedObject> {
|
||||
|
||||
let controller = CoreStoreFetchedResultsController(
|
||||
context: context,
|
||||
fetchRequest: CoreStoreFetchRequest().dynamicCast(),
|
||||
from: from?.bridgeToSwift,
|
||||
from: from.bridgeToSwift,
|
||||
sectionBy: sectionBy?.bridgeToSwift,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
|
||||
@@ -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 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?) rethrows {
|
||||
public func setValue(_ value: Any?, forKvcKey KVCKey: KeyPath, didSetValue: () -> Void) {
|
||||
|
||||
self.willChangeValue(forKey: KVCKey)
|
||||
defer {
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -91,7 +91,7 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
@nonobjc
|
||||
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
|
||||
|
||||
@@ -260,20 +260,19 @@ public final class ObjectMonitor<D: DynamicObject>: Equatable {
|
||||
|
||||
private init(context: NSManagedObjectContext, object: ObjectType) {
|
||||
|
||||
let rawObject = object.cs_toRaw()
|
||||
let objectID = object.cs_id()
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
fetchRequest.entity = rawObject.entity
|
||||
fetchRequest.entity = objectID.entity
|
||||
fetchRequest.fetchLimit = 0
|
||||
fetchRequest.resultType = .managedObjectResultType
|
||||
fetchRequest.sortDescriptors = []
|
||||
fetchRequest.includesPendingChanges = false
|
||||
fetchRequest.shouldRefreshRefetchedObjects = true
|
||||
|
||||
let objectID = rawObject.objectID
|
||||
let fetchedResultsController = CoreStoreFetchedResultsController(
|
||||
context: context,
|
||||
fetchRequest: fetchRequest.dynamicCast(),
|
||||
from: nil as From<ObjectType>?,
|
||||
from: From<ObjectType>([objectID.persistentStore?.configurationName]),
|
||||
applyFetchClauses: Where("SELF", isEqualTo: objectID).applyToFetchRequest
|
||||
)
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ public extension DynamicObject where Self: CoreStoreObject {
|
||||
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>
|
||||
}
|
||||
@@ -73,6 +74,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
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 {
|
||||
|
||||
@@ -90,10 +92,23 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: KeyPath,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: String? = nil,
|
||||
renamingIdentifier: String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { nil },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,10 +126,24 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: KeyPath,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: String? = nil,
|
||||
renamingIdentifier: String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,10 +161,24 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: KeyPath,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: String? = nil,
|
||||
renamingIdentifier: String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,10 +196,24 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: KeyPath,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: String? = nil,
|
||||
renamingIdentifier: String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,54 +244,64 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?)
|
||||
internal let versionHashModifier: String?
|
||||
internal let renamingIdentifier: String?
|
||||
|
||||
internal var parentObject: () -> CoreStoreObject = {
|
||||
|
||||
CoreStore.abort("Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types.")
|
||||
}
|
||||
internal let affectedByKeyPaths: () -> Set<String>
|
||||
internal weak var parentObject: CoreStoreObject?
|
||||
|
||||
internal var nativeValue: NSManagedObject? {
|
||||
|
||||
get {
|
||||
|
||||
let object = self.parentObject() as! O
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return object.rawObject!.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
didGetValue: { $0 as! NSManagedObject? }
|
||||
self.parentObject != nil,
|
||||
"Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return withExtendedLifetime(self.parentObject! as! O) { (object: O) in
|
||||
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return object.rawObject!.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
didGetValue: { $0 as! NSManagedObject? }
|
||||
)
|
||||
}
|
||||
}
|
||||
set {
|
||||
|
||||
let object = self.parentObject() as! O
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isEditableInContext() == true,
|
||||
"Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction."
|
||||
)
|
||||
object.rawObject!.setValue(
|
||||
newValue,
|
||||
forKvcKey: self.keyPath
|
||||
self.parentObject != nil,
|
||||
"Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return withExtendedLifetime(self.parentObject! as! O) { (object: O) in
|
||||
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isEditableInContext() == true,
|
||||
"Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction."
|
||||
)
|
||||
object.rawObject!.setValue(
|
||||
newValue,
|
||||
forKvcKey: self.keyPath
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private init(keyPath: KeyPath, inverseKeyPath: @escaping () -> KeyPath?, deleteRule: DeleteRule, versionHashModifier: String?, renamingIdentifier: String?) {
|
||||
private init(keyPath: KeyPath, inverseKeyPath: @escaping () -> KeyPath?, deleteRule: DeleteRule, versionHashModifier: String?, renamingIdentifier: String?, affectedByKeyPaths: @autoclosure @escaping () -> Set<String>) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.deleteRule = deleteRule.nativeValue
|
||||
self.inverse = (D.self, inverseKeyPath)
|
||||
self.versionHashModifier = versionHashModifier
|
||||
self.renamingIdentifier = renamingIdentifier
|
||||
self.affectedByKeyPaths = affectedByKeyPaths
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,6 +318,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
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 {
|
||||
|
||||
@@ -270,10 +338,27 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public convenience init(_ keyPath: KeyPath, minCount: Int = 0, maxCount: Int = 0, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: KeyPath,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: String? = nil,
|
||||
renamingIdentifier: String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, minCount: minCount, maxCount: maxCount, inverseKeyPath: { nil }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
inverseKeyPath: { nil },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,10 +378,28 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public convenience init(_ keyPath: KeyPath, minCount: Int = 0, maxCount: Int = 0, inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: KeyPath,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: String? = nil,
|
||||
renamingIdentifier: String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, minCount: minCount, maxCount: maxCount, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -316,10 +419,28 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public convenience init(_ keyPath: KeyPath, minCount: Int = 0, maxCount: Int = 0, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: KeyPath,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: String? = nil,
|
||||
renamingIdentifier: String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, minCount: minCount, maxCount: maxCount, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -339,10 +460,28 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public convenience init(_ keyPath: KeyPath, minCount: Int = 0, maxCount: Int = 0, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: KeyPath,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: String? = nil,
|
||||
renamingIdentifier: String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, minCount: minCount, maxCount: maxCount, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -374,48 +513,57 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?)
|
||||
internal let versionHashModifier: String?
|
||||
internal let renamingIdentifier: String?
|
||||
|
||||
internal var parentObject: () -> CoreStoreObject = {
|
||||
|
||||
CoreStore.abort("Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types.")
|
||||
}
|
||||
internal let affectedByKeyPaths: () -> Set<String>
|
||||
internal weak var parentObject: CoreStoreObject?
|
||||
|
||||
internal var nativeValue: NSOrderedSet {
|
||||
|
||||
get {
|
||||
|
||||
let object = self.parentObject() as! O
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return object.rawObject!.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
didGetValue: { ($0 as! NSOrderedSet?) ?? [] }
|
||||
self.parentObject != nil,
|
||||
"Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return withExtendedLifetime(self.parentObject! as! O) { (object: O) in
|
||||
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return object.rawObject!.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
didGetValue: { ($0 as! NSOrderedSet?) ?? [] }
|
||||
)
|
||||
}
|
||||
}
|
||||
set {
|
||||
|
||||
let object = self.parentObject() as! O
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isEditableInContext() == true,
|
||||
"Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction."
|
||||
)
|
||||
object.rawObject!.setValue(
|
||||
newValue,
|
||||
forKvcKey: self.keyPath
|
||||
self.parentObject != nil,
|
||||
"Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return withExtendedLifetime(self.parentObject! as! O) { (object: O) in
|
||||
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isEditableInContext() == true,
|
||||
"Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction."
|
||||
)
|
||||
object.rawObject!.setValue(
|
||||
newValue,
|
||||
forKvcKey: self.keyPath
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private init(keyPath: String, minCount: Int, maxCount: Int, inverseKeyPath: @escaping () -> String?, deleteRule: DeleteRule, versionHashModifier: String?, renamingIdentifier: String?) {
|
||||
private init(keyPath: String, minCount: Int, maxCount: Int, inverseKeyPath: @escaping () -> String?, deleteRule: DeleteRule, versionHashModifier: String?, renamingIdentifier: String?, affectedByKeyPaths: @autoclosure @escaping () -> Set<String>) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.deleteRule = deleteRule.nativeValue
|
||||
@@ -426,6 +574,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
let range = (Swift.max(0, minCount) ... maxCount)
|
||||
self.minCount = range.lowerBound
|
||||
self.maxCount = range.upperBound
|
||||
self.affectedByKeyPaths = affectedByKeyPaths
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,6 +591,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
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 {
|
||||
|
||||
@@ -462,10 +612,27 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: KeyPath,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
versionHashModifier: String? = nil,
|
||||
renamingIdentifier: String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { nil },
|
||||
deleteRule: deleteRule,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -485,10 +652,28 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: KeyPath,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
versionHashModifier: String? = nil,
|
||||
renamingIdentifier: String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -508,10 +693,28 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: KeyPath,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
versionHashModifier: String? = nil,
|
||||
renamingIdentifier: String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -531,10 +734,28 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: KeyPath,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
versionHashModifier: String? = nil,
|
||||
renamingIdentifier: String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -566,48 +787,57 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?)
|
||||
internal let versionHashModifier: String?
|
||||
internal let renamingIdentifier: String?
|
||||
|
||||
internal var parentObject: () -> CoreStoreObject = {
|
||||
|
||||
CoreStore.abort("Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types.")
|
||||
}
|
||||
internal let affectedByKeyPaths: () -> Set<String>
|
||||
internal weak var parentObject: CoreStoreObject?
|
||||
|
||||
internal var nativeValue: NSSet {
|
||||
|
||||
get {
|
||||
|
||||
let object = self.parentObject() as! O
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return object.rawObject!.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
didGetValue: { ($0 as! NSSet?) ?? [] }
|
||||
self.parentObject != nil,
|
||||
"Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return withExtendedLifetime(self.parentObject! as! O) { (object: O) in
|
||||
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return object.rawObject!.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
didGetValue: { ($0 as! NSSet?) ?? [] }
|
||||
)
|
||||
}
|
||||
}
|
||||
set {
|
||||
|
||||
let object = self.parentObject() as! O
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isEditableInContext() == true,
|
||||
"Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction."
|
||||
)
|
||||
object.rawObject!.setValue(
|
||||
newValue,
|
||||
forKvcKey: self.keyPath
|
||||
self.parentObject != nil,
|
||||
"Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return withExtendedLifetime(self.parentObject! as! O) { (object: O) in
|
||||
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isEditableInContext() == true,
|
||||
"Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction."
|
||||
)
|
||||
object.rawObject!.setValue(
|
||||
newValue,
|
||||
forKvcKey: self.keyPath
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private init(keyPath: KeyPath, inverseKeyPath: @escaping () -> KeyPath?, deleteRule: DeleteRule, minCount: Int, maxCount: Int, versionHashModifier: String?, renamingIdentifier: String?) {
|
||||
private init(keyPath: KeyPath, inverseKeyPath: @escaping () -> KeyPath?, deleteRule: DeleteRule, minCount: Int, maxCount: Int, versionHashModifier: String?, renamingIdentifier: String?, affectedByKeyPaths: @autoclosure @escaping () -> Set<String>) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.deleteRule = deleteRule.nativeValue
|
||||
@@ -618,6 +848,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
let range = (Swift.max(0, minCount) ... maxCount)
|
||||
self.minCount = range.lowerBound
|
||||
self.maxCount = range.upperBound
|
||||
self.affectedByKeyPaths = affectedByKeyPaths
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,7 +885,7 @@ extension RelationshipContainer.ToManyOrdered: RandomAccessCollection {
|
||||
public func makeIterator() -> Iterator {
|
||||
|
||||
let iterator = self.nativeValue.makeIterator()
|
||||
return AnyIterator({ D.cs_fromRaw(object: iterator.next() as! NSManagedObject) })
|
||||
return AnyIterator({ iterator.next().flatMap({ D.cs_fromRaw(object: $0 as! NSManagedObject) }) })
|
||||
}
|
||||
|
||||
|
||||
@@ -709,7 +940,7 @@ extension RelationshipContainer.ToManyUnordered: Sequence {
|
||||
public func makeIterator() -> Iterator {
|
||||
|
||||
let iterator = self.nativeValue.makeIterator()
|
||||
return AnyIterator({ D.cs_fromRaw(object: iterator.next() as! NSManagedObject) })
|
||||
return AnyIterator({ iterator.next().flatMap({ D.cs_fromRaw(object: $0 as! NSManagedObject) }) })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -984,7 +1215,8 @@ internal protocol RelationshipProtocol: class {
|
||||
var isOrdered: Bool { get }
|
||||
var deleteRule: NSDeleteRule { get }
|
||||
var inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?) { get }
|
||||
var parentObject: () -> CoreStoreObject { get set }
|
||||
var affectedByKeyPaths: () -> Set<String> { get }
|
||||
weak var parentObject: CoreStoreObject? { get set }
|
||||
var versionHashModifier: String? { get }
|
||||
var renamingIdentifier: String? { get }
|
||||
var minCount: Int { get }
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// LegacyXcodeDataModelSchema.swift
|
||||
// UnsafeDataModelSchema.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
@@ -27,18 +27,18 @@ import CoreData
|
||||
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(
|
||||
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)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -148,7 +148,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable {
|
||||
self.init(NSPredicate(format: "\(keyPath) == nil"))
|
||||
|
||||
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 {
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,7 +32,7 @@ import Foundation
|
||||
/**
|
||||
A `SchemaMappingProvider` that tries to infer model migration between two `DynamicSchema` versions by loading an xcmappingmodel file from the specified `Bundle`. Throws `CoreStoreError.mappingModelNotFound` if the xcmappingmodel file cannot be found, or if the xcmappingmodel doesn't resolve the source and destination `DynamicSchema`.
|
||||
*/
|
||||
final class XcodeSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
public final class XcodeSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
|
||||
/**
|
||||
The source model version for the mapping.
|
||||
|
||||
Reference in New Issue
Block a user