Merge branch 'develop' into prototype/containers

# Conflicts:
#	CoreStore.xcodeproj/project.pbxproj
#	Sources/DataStack+Transaction.swift
This commit is contained in:
John Estropia
2022-01-12 16:58:10 +09:00
146 changed files with 2645 additions and 10235 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = "CoreStore" s.name = "CoreStore"
s.version = "8.0.1" s.version = "8.1.0"
s.swift_version = "5.4" s.swift_version = "5.5"
s.license = "MIT" s.license = "MIT"
s.homepage = "https://github.com/JohnEstropia/CoreStore" s.homepage = "https://github.com/JohnEstropia/CoreStore"
s.documentation_url = "https://JohnEstropia.github.io/CoreStore" s.documentation_url = "https://JohnEstropia.github.io/CoreStore"
+8 -44
View File
@@ -835,9 +835,6 @@
B5DBE2D31C991B3E00B5CEFA /* CSDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DBE2D11C991B3E00B5CEFA /* CSDataStack.swift */; }; B5DBE2D31C991B3E00B5CEFA /* CSDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DBE2D11C991B3E00B5CEFA /* CSDataStack.swift */; };
B5DBE2D41C991B3E00B5CEFA /* CSDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DBE2D11C991B3E00B5CEFA /* CSDataStack.swift */; }; B5DBE2D41C991B3E00B5CEFA /* CSDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DBE2D11C991B3E00B5CEFA /* CSDataStack.swift */; };
B5DBE2D51C991B3E00B5CEFA /* CSDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DBE2D11C991B3E00B5CEFA /* CSDataStack.swift */; }; B5DBE2D51C991B3E00B5CEFA /* CSDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DBE2D11C991B3E00B5CEFA /* CSDataStack.swift */; };
B5DBE2DF1C9939E100B5CEFA /* BridgingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B5DBE2DE1C9939E100B5CEFA /* BridgingTests.m */; };
B5DBE2E01C9939E100B5CEFA /* BridgingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B5DBE2DE1C9939E100B5CEFA /* BridgingTests.m */; };
B5DBE2E11C9939E100B5CEFA /* BridgingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B5DBE2DE1C9939E100B5CEFA /* BridgingTests.m */; };
B5DC47C61C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DC47C51C93D22900FA3BF3 /* MigrationChainTests.swift */; }; B5DC47C61C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DC47C51C93D22900FA3BF3 /* MigrationChainTests.swift */; };
B5DC47C71C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DC47C51C93D22900FA3BF3 /* MigrationChainTests.swift */; }; B5DC47C71C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DC47C51C93D22900FA3BF3 /* MigrationChainTests.swift */; };
B5DC47C81C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DC47C51C93D22900FA3BF3 /* MigrationChainTests.swift */; }; B5DC47C81C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DC47C51C93D22900FA3BF3 /* MigrationChainTests.swift */; };
@@ -924,10 +921,6 @@
B5ECDBEE1CA6BF2000C7F112 /* CSFrom.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBEB1CA6BF2000C7F112 /* CSFrom.swift */; }; B5ECDBEE1CA6BF2000C7F112 /* CSFrom.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBEB1CA6BF2000C7F112 /* CSFrom.swift */; };
B5ECDBEF1CA6BF2000C7F112 /* CSFrom.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBEB1CA6BF2000C7F112 /* CSFrom.swift */; }; B5ECDBEF1CA6BF2000C7F112 /* CSFrom.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBEB1CA6BF2000C7F112 /* CSFrom.swift */; };
B5ECDBF01CA6BF2000C7F112 /* CSFrom.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBEB1CA6BF2000C7F112 /* CSFrom.swift */; }; B5ECDBF01CA6BF2000C7F112 /* CSFrom.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBEB1CA6BF2000C7F112 /* CSFrom.swift */; };
B5ECDBF91CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBF81CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift */; };
B5ECDBFB1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBF81CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift */; };
B5ECDBFC1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBF81CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift */; };
B5ECDBFD1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBF81CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift */; };
B5ECDBFF1CA80CBA00C7F112 /* CSWhere.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBFE1CA80CBA00C7F112 /* CSWhere.swift */; }; B5ECDBFF1CA80CBA00C7F112 /* CSWhere.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBFE1CA80CBA00C7F112 /* CSWhere.swift */; };
B5ECDC011CA80CBA00C7F112 /* CSWhere.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBFE1CA80CBA00C7F112 /* CSWhere.swift */; }; B5ECDC011CA80CBA00C7F112 /* CSWhere.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBFE1CA80CBA00C7F112 /* CSWhere.swift */; };
B5ECDC021CA80CBA00C7F112 /* CSWhere.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBFE1CA80CBA00C7F112 /* CSWhere.swift */; }; B5ECDC021CA80CBA00C7F112 /* CSWhere.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBFE1CA80CBA00C7F112 /* CSWhere.swift */; };
@@ -1220,9 +1213,6 @@
B5DAFB492203E01D003FCCD0 /* KeyPathGenericBindings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPathGenericBindings.swift; sourceTree = "<group>"; }; B5DAFB492203E01D003FCCD0 /* KeyPathGenericBindings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPathGenericBindings.swift; sourceTree = "<group>"; };
B5DBE2CC1C9914A900B5CEFA /* CSCoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSCoreStore.swift; sourceTree = "<group>"; }; B5DBE2CC1C9914A900B5CEFA /* CSCoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSCoreStore.swift; sourceTree = "<group>"; };
B5DBE2D11C991B3E00B5CEFA /* CSDataStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSDataStack.swift; sourceTree = "<group>"; }; B5DBE2D11C991B3E00B5CEFA /* CSDataStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSDataStack.swift; sourceTree = "<group>"; };
B5DBE2DA1C9939E100B5CEFA /* CoreStoreTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CoreStoreTests-Bridging-Header.h"; sourceTree = "<group>"; };
B5DBE2DD1C9939E100B5CEFA /* BridgingTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BridgingTests.h; sourceTree = "<group>"; };
B5DBE2DE1C9939E100B5CEFA /* BridgingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BridgingTests.m; sourceTree = "<group>"; };
B5DC47C51C93D22900FA3BF3 /* MigrationChainTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationChainTests.swift; sourceTree = "<group>"; }; B5DC47C51C93D22900FA3BF3 /* MigrationChainTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationChainTests.swift; sourceTree = "<group>"; };
B5DC47C91C93D9C800FA3BF3 /* StorageInterfaceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageInterfaceTests.swift; sourceTree = "<group>"; }; B5DC47C91C93D9C800FA3BF3 /* StorageInterfaceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageInterfaceTests.swift; sourceTree = "<group>"; };
B5DE522A230BD7CC00A22534 /* Internals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Internals.swift; sourceTree = "<group>"; }; B5DE522A230BD7CC00A22534 /* Internals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Internals.swift; sourceTree = "<group>"; };
@@ -1271,7 +1261,6 @@
B5ECDBDE1CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSBaseDataTransaction+Querying.swift"; sourceTree = "<group>"; }; B5ECDBDE1CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSBaseDataTransaction+Querying.swift"; sourceTree = "<group>"; };
B5ECDBE41CA6BEA300C7F112 /* CSClauseTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSClauseTypes.swift; sourceTree = "<group>"; }; B5ECDBE41CA6BEA300C7F112 /* CSClauseTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSClauseTypes.swift; sourceTree = "<group>"; };
B5ECDBEB1CA6BF2000C7F112 /* CSFrom.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSFrom.swift; sourceTree = "<group>"; }; B5ECDBEB1CA6BF2000C7F112 /* CSFrom.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSFrom.swift; sourceTree = "<group>"; };
B5ECDBF81CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+ObjectiveC.swift"; sourceTree = "<group>"; };
B5ECDBFE1CA80CBA00C7F112 /* CSWhere.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSWhere.swift; sourceTree = "<group>"; }; B5ECDBFE1CA80CBA00C7F112 /* CSWhere.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSWhere.swift; sourceTree = "<group>"; };
B5ECDC041CA8138100C7F112 /* CSOrderBy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSOrderBy.swift; sourceTree = "<group>"; }; B5ECDC041CA8138100C7F112 /* CSOrderBy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSOrderBy.swift; sourceTree = "<group>"; };
B5ECDC0A1CA8161B00C7F112 /* CSGroupBy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSGroupBy.swift; sourceTree = "<group>"; }; B5ECDC0A1CA8161B00C7F112 /* CSGroupBy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSGroupBy.swift; sourceTree = "<group>"; };
@@ -1416,8 +1405,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
B5AA37FE235DEBD700FFD4B9 /* BaseTests */, B5AA37FE235DEBD700FFD4B9 /* BaseTests */,
B5DBE2DD1C9939E100B5CEFA /* BridgingTests.h */,
B5DBE2DE1C9939E100B5CEFA /* BridgingTests.m */,
B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */, B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */,
B5519A3F1CA1B17B002BEF78 /* ErrorTests.swift */, B5519A3F1CA1B17B002BEF78 /* ErrorTests.swift */,
B52557871D02DE8100E51965 /* FetchTests.swift */, B52557871D02DE8100E51965 /* FetchTests.swift */,
@@ -1452,7 +1439,6 @@
children = ( children = (
B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */, B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */,
2F03A53E19C5C6DA005002A5 /* Info.plist */, 2F03A53E19C5C6DA005002A5 /* Info.plist */,
B5DBE2DA1C9939E100B5CEFA /* CoreStoreTests-Bridging-Header.h */,
); );
name = "Supporting Files"; name = "Supporting Files";
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1815,7 +1801,6 @@
B501FDDB1CA8D03600BE22EF /* Observing */, B501FDDB1CA8D03600BE22EF /* Observing */,
B5E1B5A61CAA49CE007FD580 /* Migrating */, B5E1B5A61CAA49CE007FD580 /* Migrating */,
B53FBA101CAB607000F0D40A /* Convenience */, B53FBA101CAB607000F0D40A /* Convenience */,
B5E222211CA4DE5700BA2E95 /* Internal */,
); );
name = ObjectiveC; name = ObjectiveC;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1831,14 +1816,6 @@
name = Migrating; name = Migrating;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
B5E222211CA4DE5700BA2E95 /* Internal */ = {
isa = PBXGroup;
children = (
B5ECDBF81CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift */,
);
name = Internal;
sourceTree = "<group>";
};
B5E2222F1CA5339200BA2E95 /* Fetching and Querying */ = { B5E2222F1CA5339200BA2E95 /* Fetching and Querying */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -2353,7 +2330,6 @@
B56E4ED423CDB54A00E1708C /* FieldProtocol.swift in Sources */, B56E4ED423CDB54A00E1708C /* FieldProtocol.swift in Sources */,
B509D7C423C848DA00F42824 /* Relationship.ToOne.swift in Sources */, B509D7C423C848DA00F42824 /* Relationship.ToOne.swift in Sources */,
B5E84F221AFF84860064E85B /* ObjectMonitor.swift in Sources */, B5E84F221AFF84860064E85B /* ObjectMonitor.swift in Sources */,
B5ECDBF91CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */,
B5CA2B081F7E5ACA004B1936 /* WhereClauseType.swift in Sources */, B5CA2B081F7E5ACA004B1936 /* WhereClauseType.swift in Sources */,
B50E17612351FA66004F033C /* Internals.Closure.swift in Sources */, B50E17612351FA66004F033C /* Internals.Closure.swift in Sources */,
B50C3EEA23D1601400B29880 /* FieldCoders.swift in Sources */, B50C3EEA23D1601400B29880 /* FieldCoders.swift in Sources */,
@@ -2593,7 +2569,6 @@
B580857A1CDF808C004C2EEB /* SetupTests.swift in Sources */, B580857A1CDF808C004C2EEB /* SetupTests.swift in Sources */,
B59A51832256C85E00CEF3C5 /* VersionLockTests.swift in Sources */, B59A51832256C85E00CEF3C5 /* VersionLockTests.swift in Sources */,
B5489F4C1CF5F743008B4978 /* BaseTestCase.swift in Sources */, B5489F4C1CF5F743008B4978 /* BaseTestCase.swift in Sources */,
B5DBE2DF1C9939E100B5CEFA /* BridgingTests.m in Sources */,
B57D27BE1D0BBE8200539C58 /* BaseTestDataTestCase.swift in Sources */, B57D27BE1D0BBE8200539C58 /* BaseTestDataTestCase.swift in Sources */,
B5489F3F1CF5EEBC008B4978 /* TestEntity1.swift in Sources */, B5489F3F1CF5EEBC008B4978 /* TestEntity1.swift in Sources */,
B57D27C21D0BC20100539C58 /* QueryTests.swift in Sources */, B57D27C21D0BC20100539C58 /* QueryTests.swift in Sources */,
@@ -2606,7 +2581,6 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
82BA18B61C4BBD3F00A0916E /* DataStack+Querying.swift in Sources */, 82BA18B61C4BBD3F00A0916E /* DataStack+Querying.swift in Sources */,
B5ECDBFB1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */,
B5635D152356C39500B80E6B /* DiffableDataSource.CollectionViewAdapter-UIKit.swift in Sources */, B5635D152356C39500B80E6B /* DiffableDataSource.CollectionViewAdapter-UIKit.swift in Sources */,
B5CA2B091F7E5ACA004B1936 /* WhereClauseType.swift in Sources */, B5CA2B091F7E5ACA004B1936 /* WhereClauseType.swift in Sources */,
B5C976E81C6E3A5D00B1AF90 /* Internals.CoreStoreFetchedResultsController.swift in Sources */, B5C976E81C6E3A5D00B1AF90 /* Internals.CoreStoreFetchedResultsController.swift in Sources */,
@@ -2834,7 +2808,6 @@
B5D8CA7D2346EC610055D7D1 /* ListPublisherTests.swift in Sources */, B5D8CA7D2346EC610055D7D1 /* ListPublisherTests.swift in Sources */,
B52557751D02791400E51965 /* WhereTests.swift in Sources */, B52557751D02791400E51965 /* WhereTests.swift in Sources */,
B5DC47C71C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */, B5DC47C71C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */,
B5DBE2E01C9939E100B5CEFA /* BridgingTests.m in Sources */,
B5220E0D1D0D0D19009BC71E /* ImportTests.swift in Sources */, B5220E0D1D0D0D19009BC71E /* ImportTests.swift in Sources */,
B5D339B51E925C2B00C880DE /* DynamicModelTests.swift in Sources */, B5D339B51E925C2B00C880DE /* DynamicModelTests.swift in Sources */,
B525576D1CFAF18F00E51965 /* IntoTests.swift in Sources */, B525576D1CFAF18F00E51965 /* IntoTests.swift in Sources */,
@@ -2928,7 +2901,6 @@
B5519A4D1CA1F4FB002BEF78 /* CSError.swift in Sources */, B5519A4D1CA1F4FB002BEF78 /* CSError.swift in Sources */,
B5E1B5AC1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */, B5E1B5AC1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */,
B52DD1961BE1F92500949AFE /* DataStack.swift in Sources */, B52DD1961BE1F92500949AFE /* DataStack.swift in Sources */,
B5ECDBFD1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */,
B56ED34F263FF64B00ACCCB8 /* Internals.AppGroupsManager.swift in Sources */, B56ED34F263FF64B00ACCCB8 /* Internals.AppGroupsManager.swift in Sources */,
B52DD1BD1BE1F94300949AFE /* NSManagedObject+Convenience.swift in Sources */, B52DD1BD1BE1F94300949AFE /* NSManagedObject+Convenience.swift in Sources */,
B5831F4222126FED00D8604C /* KeyPathGenericBindings.swift in Sources */, B5831F4222126FED00D8604C /* KeyPathGenericBindings.swift in Sources */,
@@ -3090,7 +3062,6 @@
B52557761D02791400E51965 /* WhereTests.swift in Sources */, B52557761D02791400E51965 /* WhereTests.swift in Sources */,
B5D8CA7E2346EC610055D7D1 /* ListPublisherTests.swift in Sources */, B5D8CA7E2346EC610055D7D1 /* ListPublisherTests.swift in Sources */,
B5DC47C81C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */, B5DC47C81C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */,
B5DBE2E11C9939E100B5CEFA /* BridgingTests.m in Sources */,
B5220E0E1D0D0D19009BC71E /* ImportTests.swift in Sources */, B5220E0E1D0D0D19009BC71E /* ImportTests.swift in Sources */,
B525576E1CFAF18F00E51965 /* IntoTests.swift in Sources */, B525576E1CFAF18F00E51965 /* IntoTests.swift in Sources */,
B5D339B61E925C2B00C880DE /* DynamicModelTests.swift in Sources */, B5D339B61E925C2B00C880DE /* DynamicModelTests.swift in Sources */,
@@ -3120,7 +3091,6 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
B56321A91BD65219006C9394 /* Progress+Convenience.swift in Sources */, B56321A91BD65219006C9394 /* Progress+Convenience.swift in Sources */,
B5ECDBFC1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */,
B5635D162356C39500B80E6B /* DiffableDataSource.CollectionViewAdapter-UIKit.swift in Sources */, B5635D162356C39500B80E6B /* DiffableDataSource.CollectionViewAdapter-UIKit.swift in Sources */,
B5CA2B0A1F7E5ACA004B1936 /* WhereClauseType.swift in Sources */, B5CA2B0A1F7E5ACA004B1936 /* WhereClauseType.swift in Sources */,
B5C976E91C6E3A5E00B1AF90 /* Internals.CoreStoreFetchedResultsController.swift in Sources */, B5C976E91C6E3A5E00B1AF90 /* Internals.CoreStoreFetchedResultsController.swift in Sources */,
@@ -3505,7 +3475,7 @@
DYLIB_INSTALL_NAME_BASE = "@rpath"; DYLIB_INSTALL_NAME_BASE = "@rpath";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 8.0.1; MARKETING_VERSION = 8.1.0;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3528,7 +3498,7 @@
DYLIB_INSTALL_NAME_BASE = "@rpath"; DYLIB_INSTALL_NAME_BASE = "@rpath";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 8.0.1; MARKETING_VERSION = 8.1.0;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3554,7 +3524,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = CoreStoreTests; PRODUCT_NAME = CoreStoreTests;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_SWIFT3_OBJC_INFERENCE = Off;
}; };
@@ -3570,7 +3539,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = CoreStoreTests; PRODUCT_NAME = CoreStoreTests;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h";
SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_SWIFT3_OBJC_INFERENCE = Off;
}; };
name = Release; name = Release;
@@ -3588,7 +3556,7 @@
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 8.0.1; MARKETING_VERSION = 8.1.0;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3615,7 +3583,7 @@
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 8.0.1; MARKETING_VERSION = 8.1.0;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3640,7 +3608,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = CoreStoreTests; PRODUCT_NAME = CoreStoreTests;
SDKROOT = appletvos; SDKROOT = appletvos;
SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_SWIFT3_OBJC_INFERENCE = Off;
TARGETED_DEVICE_FAMILY = 3; TARGETED_DEVICE_FAMILY = 3;
@@ -3659,7 +3626,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = CoreStoreTests; PRODUCT_NAME = CoreStoreTests;
SDKROOT = appletvos; SDKROOT = appletvos;
SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h";
SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_SWIFT3_OBJC_INFERENCE = Off;
TARGETED_DEVICE_FAMILY = 3; TARGETED_DEVICE_FAMILY = 3;
}; };
@@ -3681,7 +3647,7 @@
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 8.0.1; MARKETING_VERSION = 8.1.0;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3710,7 +3676,7 @@
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 8.0.1; MARKETING_VERSION = 8.1.0;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3736,7 +3702,6 @@
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore; PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore;
PRODUCT_NAME = CoreStoreTests; PRODUCT_NAME = CoreStoreTests;
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_SWIFT3_OBJC_INFERENCE = Off;
}; };
@@ -3757,7 +3722,6 @@
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore; PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore;
PRODUCT_NAME = CoreStoreTests; PRODUCT_NAME = CoreStoreTests;
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h";
SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_SWIFT3_OBJC_INFERENCE = Off;
}; };
name = Release; name = Release;
@@ -3776,7 +3740,7 @@
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 8.0.1; MARKETING_VERSION = 8.1.0;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3805,7 +3769,7 @@
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 8.0.1; MARKETING_VERSION = 8.1.0;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1200" LastUpgradeVersion = "1300"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1200" LastUpgradeVersion = "1300"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1200" LastUpgradeVersion = "1300"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1200" LastUpgradeVersion = "1300"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
-3
View File
@@ -7,7 +7,4 @@
<FileRef <FileRef
location = "group:CoreStore.xcodeproj"> location = "group:CoreStore.xcodeproj">
</FileRef> </FileRef>
<FileRef
location = "group:LegacyDemo/LegacyDemo.xcodeproj">
</FileRef>
</Workspace> </Workspace>
-30
View File
@@ -1,30 +0,0 @@
//
// BridgingTests.h
// CoreStore
//
// Copyright © 2018 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#import <XCTest/XCTest.h>
@interface BridgingTests : XCTestCase
@end
-261
View File
@@ -1,261 +0,0 @@
//
// BridgingTests.m
// CoreStore
//
// Copyright © 2018 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#import "BridgingTests.h"
#import <CoreStore/CoreStore.h>
#import <CoreStore/CoreStore-Swift.h>
#import "CoreStoreTests-Swift.h"
@import CoreData;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// MARK: - BridgingTests
@implementation BridgingTests
- (void)test_ThatFlags_HaveCorrectValues {
XCTAssertEqual(CSLocalStorageOptionsNone, 0);
XCTAssertEqual(CSLocalStorageOptionsRecreateStoreOnModelMismatch, 1);
XCTAssertEqual(CSLocalStorageOptionsPreventProgressiveMigration, 2);
XCTAssertEqual(CSLocalStorageOptionsAllowSynchronousLightweightMigration, 4);
}
- (void)test_ThatKeyPaths_AreCorrect {
XCTAssertEqualObjects(CSKeyPath(TestEntity1, testNumber), @"testNumber");
XCTAssertEqualObjects(CSKeyPath(TestEntity1, testString), @"testString");
XCTAssertEqualObjects(CSKeyPathOperator(count, TestEntity1, testString), @"@count.testString");
XCTAssertEqualObjects(CSKeyPathOperator(max, TestEntity1, testNumber), @"@max.testNumber");
}
- (void)test_ThatFromClauses_BridgeCorrectly {
{
CSFrom *from = CSFromClass([TestEntity1 class]);
XCTAssertEqualObjects(from.entityClass, [TestEntity1 class]);
XCTAssertNil(from.configurations);
}
{
CSFrom *from = CSFromClass([TestEntity1 class], [NSNull null]);
XCTAssertEqualObjects(from.entityClass, [TestEntity1 class]);
NSArray *configurations = @[[NSNull null]];
XCTAssertEqualObjects(from.configurations, configurations);
}
{
CSFrom *from = CSFromClass([TestEntity1 class], @"Config1");
XCTAssertEqualObjects(from.entityClass, [TestEntity1 class]);
NSArray *configurations = @[@"Config1"];
XCTAssertEqualObjects(from.configurations, configurations);
}
{
CSFrom *from = CSFromClass([TestEntity1 class], @[[NSNull null], @"Config2"]);
XCTAssertEqualObjects(from.entityClass, [TestEntity1 class]);
NSArray *configurations = @[[NSNull null], @"Config2"];
XCTAssertEqualObjects(from.configurations, configurations);
}
}
- (void)test_ThatWhereClauses_BridgeCorrectly {
{
CSWhere *where = CSWhereFormat(@"%K == %@", @"key", @"value");
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", @"key", @"value"];
XCTAssertEqualObjects(where.predicate, predicate);
}
{
CSWhere *where = CSWhereValue(YES);
NSPredicate *predicate = [NSPredicate predicateWithValue:YES];
XCTAssertEqualObjects(where.predicate, predicate);
}
{
CSWhere *where = CSWherePredicate([NSPredicate predicateWithFormat:@"%K == %@", @"key", @"value"]);
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", @"key", @"value"];
XCTAssertEqualObjects(where.predicate, predicate);
}
}
- (void)test_ThatOrderByClauses_BridgeCorrectly {
{
CSOrderBy *orderBy = CSOrderByKey(CSSortAscending(@"key"));
XCTAssertEqualObjects(orderBy.sortDescriptors, @[[NSSortDescriptor sortDescriptorWithKey:@"key" ascending:YES]]);
}
{
CSOrderBy *orderBy = CSOrderByKey(CSSortDescending(@"key"));
XCTAssertEqualObjects(orderBy.sortDescriptors, @[[NSSortDescriptor sortDescriptorWithKey:@"key" ascending:NO]]);
}
{
CSOrderBy *orderBy = CSOrderByKeys(CSSortAscending(@"key1"), CSSortDescending(@"key2"), nil);
NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"key1" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"key2" ascending:NO]];
XCTAssertEqualObjects(orderBy.sortDescriptors, sortDescriptors);
}
}
- (void)test_ThatGroupByClauses_BridgeCorrectly {
{
CSGroupBy *groupBy = CSGroupByKeyPath(@"key");
XCTAssertEqualObjects(groupBy.keyPaths, @[@"key"]);
}
{
CSGroupBy *groupBy = CSGroupByKeyPaths(@[@"key1", @"key2"]);
NSArray *keyPaths = @[@"key1", @"key2"];
XCTAssertEqualObjects(groupBy.keyPaths, keyPaths);
}
}
- (void)test_ThatTweakClauses_BridgeCorrectly {
CSTweak *tweak = CSTweakRequest(^(NSFetchRequest * _Nonnull fetchRequest) {
fetchRequest.fetchLimit = 100;
});
NSFetchRequest *request = [NSFetchRequest new];
tweak.block(request);
XCTAssertEqual(request.fetchLimit, 100);
}
- (void)test_ThatIntoClauses_BridgeCorrectly {
{
CSInto *into = CSIntoClass([TestEntity1 class]);
XCTAssertEqualObjects(into.entityClass, [TestEntity1 class]);
}
{
CSInto *into = CSIntoClass([TestEntity1 class], [NSNull null]);
XCTAssertEqualObjects(into.entityClass, [TestEntity1 class]);
XCTAssertNil(into.configuration);
}
{
CSInto *into = CSIntoClass([TestEntity1 class], @"Config1");
XCTAssertEqualObjects(into.entityClass, [TestEntity1 class]);
XCTAssertEqualObjects(into.configuration, @"Config1");
}
}
- (void)test_ThatDataStacks_BridgeCorrectly {
CSDataStack *dataStack = [[CSDataStack alloc]
initWithXcodeModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil];
XCTAssertNotNil(dataStack);
NSError *memoryError;
CSInMemoryStore *memoryStorage = [dataStack
addInMemoryStorageAndWait:[CSInMemoryStore new]
error:&memoryError];
XCTAssertNotNil(memoryStorage);
XCTAssertEqualObjects([[memoryStorage class] storeType], [CSInMemoryStore storeType]);
XCTAssertEqualObjects([[memoryStorage class] storeType], NSInMemoryStoreType);
XCTAssertNil(memoryStorage.configuration);
XCTAssertNil(memoryStorage.storeOptions);
XCTAssertNil(memoryError);
NSError *sqliteError;
CSSQLiteStore *sqliteStorage = [dataStack
addSQLiteStorageAndWait:[CSSQLiteStore new]
error:&sqliteError];
XCTAssertNotNil(sqliteStorage);
XCTAssertEqualObjects([[sqliteStorage class] storeType], [CSSQLiteStore storeType]);
XCTAssertEqualObjects([[sqliteStorage class] storeType], NSSQLiteStoreType);
XCTAssertNil(sqliteStorage.configuration);
NSDictionary *storeOptions = @{ NSSQLitePragmasOption: @{ @"journal_mode": @"WAL" },
NSBinaryStoreInsecureDecodingCompatibilityOption: @YES };
XCTAssertEqualObjects(sqliteStorage.storeOptions, storeOptions);
XCTAssertNil(sqliteError);
}
- (void)test_ThatTransactions_BridgeCorrectly {
CSDataStack *dataStack = [[CSDataStack alloc]
initWithXcodeModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil];
XCTAssertNotNil(dataStack);
[dataStack
addInMemoryStorageAndWait:[CSInMemoryStore new]
error:nil];
{
CSUnsafeDataTransaction *transaction = [dataStack beginUnsafe];
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSUnsafeDataTransaction class]]);
NSError *error;
BOOL result = [transaction commitAndWaitWithError:&error];
XCTAssertTrue(result);
XCTAssertNil(error);
}
{
XCTestExpectation *expectation = [self expectationWithDescription:@"sync"];
NSError *error;
BOOL result =
[dataStack
beginSynchronous:^(CSSynchronousDataTransaction * _Nonnull transaction) {
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSSynchronousDataTransaction class]]);
NSError *error;
XCTAssertTrue([transaction commitAndWaitWithError:&error]);
XCTAssertNil(error);
[expectation fulfill];
}
error:&error];
XCTAssertTrue(result);
XCTAssertNil(error);
}
{
XCTestExpectation *expectation = [self expectationWithDescription:@"async"];
[dataStack beginAsynchronous:^(CSAsynchronousDataTransaction * _Nonnull transaction) {
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSAsynchronousDataTransaction class]]);
[transaction
commitWithSuccess:^{
[expectation fulfill];
}
failure:^(CSError *error){
XCTFail();
}];
}];
}
[self waitForExpectationsWithTimeout:10 handler:nil];
}
@end
#pragma clang diagnostic pop
@@ -1,5 +0,0 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "BridgingTests.h"
+10 -21
View File
@@ -31,7 +31,6 @@ import CoreStore
// MARK: - ErrorTests // MARK: - ErrorTests
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
final class ErrorTests: XCTestCase { final class ErrorTests: XCTestCase {
@objc @objc
@@ -43,14 +42,12 @@ final class ErrorTests: XCTestCase {
let userInfo: NSDictionary = [:] let userInfo: NSDictionary = [:]
let objcError = error.bridgeToObjectiveC let objcError = error as NSError
XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.unknownError.rawValue) XCTAssertEqual(objcError.code, CoreStoreErrorCode.unknownError.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo) XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC let objcError2 = CoreStoreError(objcError) as NSError
XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.unknownError.rawValue) XCTAssertEqual(objcError2.code, CoreStoreErrorCode.unknownError.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo) XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
@@ -68,14 +65,12 @@ final class ErrorTests: XCTestCase {
let userInfo: NSDictionary = [ let userInfo: NSDictionary = [
"existingPersistentStoreURL": dummyURL "existingPersistentStoreURL": dummyURL
] ]
let objcError = error.bridgeToObjectiveC let objcError = error as NSError
XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue) XCTAssertEqual(objcError.code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo) XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC let objcError2 = CoreStoreError(objcError) as NSError
XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue) XCTAssertEqual(objcError2.code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo) XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
@@ -103,14 +98,12 @@ final class ErrorTests: XCTestCase {
"targetModel": schemaHistory.rawModel, "targetModel": schemaHistory.rawModel,
"targetModelVersion": version "targetModelVersion": version
] ]
let objcError = error.bridgeToObjectiveC let objcError = error as NSError
XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.mappingModelNotFound.rawValue) XCTAssertEqual(objcError.code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo) XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC let objcError2 = CoreStoreError(objcError) as NSError
XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.mappingModelNotFound.rawValue) XCTAssertEqual(objcError2.code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo) XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
@@ -128,14 +121,12 @@ final class ErrorTests: XCTestCase {
let userInfo: NSDictionary = [ let userInfo: NSDictionary = [
"localStoreURL": dummyURL "localStoreURL": dummyURL
] ]
let objcError = error.bridgeToObjectiveC let objcError = error as NSError
XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue) XCTAssertEqual(objcError.code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo) XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC let objcError2 = CoreStoreError(objcError) as NSError
XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue) XCTAssertEqual(objcError2.code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo) XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
@@ -160,14 +151,12 @@ final class ErrorTests: XCTestCase {
let userInfo: NSDictionary = [ let userInfo: NSDictionary = [
"NSError": internalError "NSError": internalError
] ]
let objcError = error.bridgeToObjectiveC let objcError = error as NSError
XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.internalError.rawValue) XCTAssertEqual(objcError.code, CoreStoreErrorCode.internalError.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo) XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC let objcError2 = CoreStoreError(objcError) as NSError
XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.internalError.rawValue) XCTAssertEqual(objcError2.code, CoreStoreErrorCode.internalError.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo) XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
-11
View File
@@ -126,15 +126,4 @@ final class IntoTests: XCTestCase {
XCTAssertNotEqual(into, Into<TestEntity1>("Config2")) XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
} }
} }
@objc
dynamic func test_ThatIntoClauses_BridgeCorrectly() {
do {
let into = Into<NSManagedObject>()
let objcInto = into.bridgeToObjectiveC
XCTAssertEqual(into, objcInto.bridgeToSwift)
}
}
} }
+2 -13
View File
@@ -41,12 +41,6 @@
B5A3916524E698C700E7E8BD /* Modern.PlacemarksDemo.Place.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A3916424E698C700E7E8BD /* Modern.PlacemarksDemo.Place.swift */; }; B5A3916524E698C700E7E8BD /* Modern.PlacemarksDemo.Place.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A3916424E698C700E7E8BD /* Modern.PlacemarksDemo.Place.swift */; };
B5A3916B24E698F900E7E8BD /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916724E698F900E7E8BD /* CoreStore.framework */; }; B5A3916B24E698F900E7E8BD /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916724E698F900E7E8BD /* CoreStore.framework */; };
B5A3916C24E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916724E698F900E7E8BD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B5A3916C24E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916724E698F900E7E8BD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B5A3916D24E698F900E7E8BD /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916824E698F900E7E8BD /* CoreStore.framework */; };
B5A3916E24E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916824E698F900E7E8BD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B5A3916F24E698F900E7E8BD /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916924E698F900E7E8BD /* CoreStore.framework */; };
B5A3917024E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916924E698F900E7E8BD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B5A3917124E698F900E7E8BD /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916A24E698F900E7E8BD /* CoreStore.framework */; };
B5A3917224E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916A24E698F900E7E8BD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B5A3917524E6990200E7E8BD /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3917424E6990200E7E8BD /* MapKit.framework */; }; B5A3917524E6990200E7E8BD /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3917424E6990200E7E8BD /* MapKit.framework */; };
B5A3917724E6990700E7E8BD /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3917624E6990700E7E8BD /* CoreLocation.framework */; }; B5A3917724E6990700E7E8BD /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3917624E6990700E7E8BD /* CoreLocation.framework */; };
B5A3917924E6991600E7E8BD /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3917824E6991600E7E8BD /* SwiftUI.framework */; }; B5A3917924E6991600E7E8BD /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3917824E6991600E7E8BD /* SwiftUI.framework */; };
@@ -116,9 +110,6 @@
dstSubfolderSpec = 10; dstSubfolderSpec = 10;
files = ( files = (
B5A3916C24E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */, B5A3916C24E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */,
B5A3917224E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */,
B5A3917024E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */,
B5A3916E24E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */,
); );
name = "Embed Frameworks"; name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@@ -234,11 +225,8 @@
files = ( files = (
B5A3917724E6990700E7E8BD /* CoreLocation.framework in Frameworks */, B5A3917724E6990700E7E8BD /* CoreLocation.framework in Frameworks */,
B5A3916B24E698F900E7E8BD /* CoreStore.framework in Frameworks */, B5A3916B24E698F900E7E8BD /* CoreStore.framework in Frameworks */,
B5A3917124E698F900E7E8BD /* CoreStore.framework in Frameworks */,
B5A3917924E6991600E7E8BD /* SwiftUI.framework in Frameworks */, B5A3917924E6991600E7E8BD /* SwiftUI.framework in Frameworks */,
B5A3917524E6990200E7E8BD /* MapKit.framework in Frameworks */, B5A3917524E6990200E7E8BD /* MapKit.framework in Frameworks */,
B5A3916F24E698F900E7E8BD /* CoreStore.framework in Frameworks */,
B5A3916D24E698F900E7E8BD /* CoreStore.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -633,7 +621,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 1160; LastSwiftUpdateCheck = 1160;
LastUpgradeCheck = 1200; LastUpgradeCheck = 1300;
TargetAttributes = { TargetAttributes = {
B5A3911824E5429200E7E8BD = { B5A3911824E5429200E7E8BD = {
CreatedOnToolsVersion = 11.6; CreatedOnToolsVersion = 11.6;
@@ -809,6 +797,7 @@
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
ONLY_ACTIVE_ARCH = YES;
}; };
name = Debug; name = Debug;
}; };
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1200" LastUpgradeVersion = "1300"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@@ -102,6 +102,7 @@ extension Modern.ColorsDemo {
try transaction.deleteAll(From<Modern.ColorsDemo.Palette>()) try transaction.deleteAll(From<Modern.ColorsDemo.Palette>())
}, },
sourceIdentifier: TransactionSource.clear,
completion: { _ in } completion: { _ in }
) )
} }
@@ -113,6 +114,7 @@ extension Modern.ColorsDemo {
_ = transaction.create(Into<Modern.ColorsDemo.Palette>()) _ = transaction.create(Into<Modern.ColorsDemo.Palette>())
}, },
sourceIdentifier: TransactionSource.add,
completion: { _ in } completion: { _ in }
) )
} }
@@ -127,6 +129,7 @@ extension Modern.ColorsDemo {
palette.setRandomHue() palette.setRandomHue()
} }
}, },
sourceIdentifier: TransactionSource.shuffle,
completion: { _ in } completion: { _ in }
) )
} }
@@ -65,9 +65,22 @@ extension Modern {
sectionIndexTransformer: { $0?.first?.uppercased() } sectionIndexTransformer: { $0?.first?.uppercased() }
) )
.where(self.filter.whereClause()) .where(self.filter.whereClause())
.orderBy(.ascending(\.$hue)) .orderBy(.ascending(\.$hue)),
sourceIdentifier: TransactionSource.refetch
) )
} }
} }
// MARK: - TransactionSource
enum TransactionSource {
case add
case delete
case shuffle
case clear
case refetch
}
} }
} }
@@ -91,7 +91,8 @@ extension Modern.ColorsDemo.UIKit {
func objectMonitor( func objectMonitor(
_ monitor: ObjectMonitor<Modern.ColorsDemo.Palette>, _ monitor: ObjectMonitor<Modern.ColorsDemo.Palette>,
didUpdateObject object: Modern.ColorsDemo.Palette, didUpdateObject object: Modern.ColorsDemo.Palette,
changedPersistentKeys: Set<KeyPathString> changedPersistentKeys: Set<KeyPathString>,
sourceIdentifier: Any?
) { ) {
self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys) self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys)
@@ -32,17 +32,26 @@ extension Modern.ColorsDemo.UIKit {
) )
/** /**
Sample 2: Once the views are created, we can start binding `ListPublisher` updates to the `DiffableDataSource`. We typically call this at the end of `viewDidLoad`. Note that the `addObserver`'s closure argument will only be called on the succeeding updates, so to immediately display the current values, we need to call `dataSource.apply()` once. Sample 2: Once the views are created, we can start binding `ListPublisher` updates to the `DiffableDataSource`. We typically call this at the end of `viewDidLoad`. Note that the `addObserver`'s closure argument will only be called on the succeeding updates, so to immediately display the current values, we need to call `dataSource.apply()` once. This example inspects the optional `transactionSource` to determine the source of the update which is helpful for debugging or for fine-tuning animations.
*/ */
private func startObservingList() { private func startObservingList() {
let dataSource = self.dataSource let dataSource = self.dataSource
self.listPublisher.addObserver(self) { (listPublisher) in self.listPublisher.addObserver(self, notifyInitial: true) { (listPublisher, transactionSource) in
dataSource.apply(listPublisher.snapshot, animatingDifferences: true) switch transactionSource as? Modern.ColorsDemo.TransactionSource {
case .add,
.delete,
.shuffle,
.clear:
dataSource.apply(listPublisher.snapshot, animatingDifferences: true)
case nil,
.refetch:
dataSource.apply(listPublisher.snapshot, animatingDifferences: false)
}
} }
dataSource.apply(self.listPublisher.snapshot, animatingDifferences: false)
} }
/** /**
@@ -74,6 +83,7 @@ extension Modern.ColorsDemo.UIKit {
transaction.delete(objectIDs: [itemID]) transaction.delete(objectIDs: [itemID])
}, },
sourceIdentifier: Modern.ColorsDemo.TransactionSource.delete,
completion: { _ in } completion: { _ in }
) )
@@ -1,597 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
B50132242344E24300FC238B /* SwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132232344E24300FC238B /* SwiftUIView.swift */; };
B50132282344E5E900FC238B /* SwiftUIContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132272344E5E900FC238B /* SwiftUIContainerViewController.swift */; };
B501323523477D2300FC238B /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B501323423477D2300FC238B /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
B503FADF1AFDC71700F90881 /* ListObserverDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADB1AFDC71700F90881 /* ListObserverDemoViewController.swift */; };
B503FAE01AFDC71700F90881 /* ObjectObserverDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADC1AFDC71700F90881 /* ObjectObserverDemoViewController.swift */; };
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADD1AFDC71700F90881 /* Palette.swift */; };
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADE1AFDC71700F90881 /* PaletteTableViewCell.swift */; };
B5125C121B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B5125C111B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel */; };
B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977D81B120B80003D50A5 /* ObserversViewController.swift */; };
B52977DD1B120F3B003D50A5 /* TransactionsDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977DC1B120F3B003D50A5 /* TransactionsDemoViewController.swift */; };
B52977DF1B120F83003D50A5 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B52977DE1B120F83003D50A5 /* MapKit.framework */; };
B52977E11B120F8A003D50A5 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B52977E01B120F8A003D50A5 /* CoreLocation.framework */; };
B52977E41B121635003D50A5 /* Place.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977E31B121635003D50A5 /* Place.swift */; };
B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54AAD4E1AF4D26E00848AE0 /* AppDelegate.swift */; };
B54AAD521AF4D26E00848AE0 /* LegacyDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B54AAD501AF4D26E00848AE0 /* LegacyDemo.xcdatamodeld */; };
B54AAD591AF4D26E00848AE0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD571AF4D26E00848AE0 /* Main.storyboard */; };
B54AAD5B1AF4D26E00848AE0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */; };
B54AAD5E1AF4D26E00848AE0 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5C1AF4D26E00848AE0 /* LaunchScreen.xib */; };
B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */; };
B5635D192357F9F700B80E6B /* CollectionViewDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5635D182357F9F700B80E6B /* CollectionViewDemoViewController.swift */; };
B5635D1B2357FA4B00B80E6B /* PaletteCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5635D1A2357FA4B00B80E6B /* PaletteCollectionViewCell.swift */; };
B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */; };
B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3311B11DF3200F4F0C6 /* UserAccount.swift */; };
B56964C91B20AC780075EE4A /* CustomLoggerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964C81B20AC780075EE4A /* CustomLoggerViewController.swift */; };
B56964D71B231AE90075EE4A /* StackSetupDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B56964D51B231AE90075EE4A /* StackSetupDemo.xcdatamodeld */; };
B56964DA1B231BCA0075EE4A /* MaleAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964D91B231BCA0075EE4A /* MaleAccount.swift */; };
B56964DC1B231BCB0075EE4A /* FemaleAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964DB1B231BCB0075EE4A /* FemaleAccount.swift */; };
B569650C1B2B36E10075EE4A /* FetchingAndQueryingDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B569650B1B2B36E10075EE4A /* FetchingAndQueryingDemoViewController.swift */; };
B56965181B2E20CC0075EE4A /* TimeZone.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965171B2E20CC0075EE4A /* TimeZone.swift */; };
B569651A1B30888A0075EE4A /* FetchingResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965191B30888A0075EE4A /* FetchingResultsViewController.swift */; };
B569651C1B30889A0075EE4A /* QueryingResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B569651B1B30889A0075EE4A /* QueryingResultsViewController.swift */; };
B56965291B3582D30075EE4A /* MigrationDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B56965271B3582D30075EE4A /* MigrationDemo.xcdatamodeld */; };
B5AA37EF2357D30300FFD4B9 /* ColorsDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AA37EE2357D30300FFD4B9 /* ColorsDemo.swift */; };
B5C37EE52357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C37EE42357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift */; };
B5E599321B5240F50084BD5F /* OrganismTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E599311B5240F50084BD5F /* OrganismTableViewCell.swift */; };
B5E89AD01C5292A2003B04A9 /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9211C202429008147CD /* CoreStore.framework */; };
B5E89AD11C5292A2003B04A9 /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9211C202429008147CD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B5EE25851B36E23C0000406B /* OrganismV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE25841B36E23C0000406B /* OrganismV1.swift */; };
B5EE25871B36E2520000406B /* OrganismV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE25861B36E2520000406B /* OrganismV2.swift */; };
B5EE258C1B36E40D0000406B /* MigrationsDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */; };
B5EE259B1B3EA4890000406B /* OrganismV3.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE259A1B3EA4890000406B /* OrganismV3.swift */; };
B5EE259E1B3EC1B20000406B /* OrganismProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE259D1B3EC1B20000406B /* OrganismProtocol.swift */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
B5E89ACF1C52929C003B04A9 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
B5E89AD11C5292A2003B04A9 /* CoreStore.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
B50132232344E24300FC238B /* SwiftUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIView.swift; sourceTree = "<group>"; };
B50132272344E5E900FC238B /* SwiftUIContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIContainerViewController.swift; sourceTree = "<group>"; };
B501323423477D2300FC238B /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
B503FADB1AFDC71700F90881 /* ListObserverDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListObserverDemoViewController.swift; sourceTree = "<group>"; };
B503FADC1AFDC71700F90881 /* ObjectObserverDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectObserverDemoViewController.swift; sourceTree = "<group>"; };
B503FADD1AFDC71700F90881 /* Palette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Palette.swift; sourceTree = "<group>"; };
B503FADE1AFDC71700F90881 /* PaletteTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaletteTableViewCell.swift; sourceTree = "<group>"; };
B5125C111B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = OrganismV2ToV3.xcmappingmodel; sourceTree = "<group>"; };
B5125C131B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = OrganismV3ToV2.xcmappingmodel; sourceTree = "<group>"; };
B52977D81B120B80003D50A5 /* ObserversViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserversViewController.swift; sourceTree = "<group>"; };
B52977DC1B120F3B003D50A5 /* TransactionsDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionsDemoViewController.swift; sourceTree = "<group>"; };
B52977DE1B120F83003D50A5 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; };
B52977E01B120F8A003D50A5 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
B52977E31B121635003D50A5 /* Place.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Place.swift; sourceTree = "<group>"; };
B54AAD491AF4D26E00848AE0 /* LegacyDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LegacyDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
B54AAD4D1AF4D26E00848AE0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B54AAD4E1AF4D26E00848AE0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
B54AAD511AF4D26E00848AE0 /* LegacyDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = LegacyDemo.xcdatamodel; sourceTree = "<group>"; };
B54AAD581AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
B54AAD5D1AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV2ToV3MigrationPolicy.swift; sourceTree = "<group>"; };
B5635D182357F9F700B80E6B /* CollectionViewDemoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewDemoViewController.swift; sourceTree = "<group>"; };
B5635D1A2357FA4B00B80E6B /* PaletteCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteCollectionViewCell.swift; sourceTree = "<group>"; };
B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackSetupDemoViewController.swift; sourceTree = "<group>"; };
B566E3311B11DF3200F4F0C6 /* UserAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserAccount.swift; sourceTree = "<group>"; };
B56964C81B20AC780075EE4A /* CustomLoggerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomLoggerViewController.swift; sourceTree = "<group>"; };
B56964D61B231AE90075EE4A /* StackSetupDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = StackSetupDemo.xcdatamodel; sourceTree = "<group>"; };
B56964D91B231BCA0075EE4A /* MaleAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaleAccount.swift; sourceTree = "<group>"; };
B56964DB1B231BCB0075EE4A /* FemaleAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FemaleAccount.swift; sourceTree = "<group>"; };
B569650B1B2B36E10075EE4A /* FetchingAndQueryingDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchingAndQueryingDemoViewController.swift; sourceTree = "<group>"; };
B56965171B2E20CC0075EE4A /* TimeZone.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimeZone.swift; sourceTree = "<group>"; };
B56965191B30888A0075EE4A /* FetchingResultsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchingResultsViewController.swift; sourceTree = "<group>"; };
B569651B1B30889A0075EE4A /* QueryingResultsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryingResultsViewController.swift; sourceTree = "<group>"; };
B56965281B3582D30075EE4A /* MigrationDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemo.xcdatamodel; sourceTree = "<group>"; };
B5AA37EE2357D30300FFD4B9 /* ColorsDemo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorsDemo.swift; sourceTree = "<group>"; };
B5BDC9211C202429008147CD /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B5C37EE42357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteCollectionSectionHeaderView.swift; sourceTree = "<group>"; };
B5E599311B5240F50084BD5F /* OrganismTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OrganismTableViewCell.swift; path = "LegacyDemo/MIgrations Demo/OrganismTableViewCell.swift"; sourceTree = SOURCE_ROOT; };
B5EE25801B36E1B00000406B /* MigrationDemoV2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemoV2.xcdatamodel; sourceTree = "<group>"; };
B5EE25841B36E23C0000406B /* OrganismV1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV1.swift; sourceTree = "<group>"; };
B5EE25861B36E2520000406B /* OrganismV2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV2.swift; sourceTree = "<group>"; };
B5EE25881B36E2750000406B /* MigrationDemoV3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemoV3.xcdatamodel; sourceTree = "<group>"; };
B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationsDemoViewController.swift; sourceTree = "<group>"; };
B5EE259A1B3EA4890000406B /* OrganismV3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV3.swift; sourceTree = "<group>"; };
B5EE259D1B3EC1B20000406B /* OrganismProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismProtocol.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
B54AAD461AF4D26E00848AE0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B501323523477D2300FC238B /* SwiftUI.framework in Frameworks */,
B5E89AD01C5292A2003B04A9 /* CoreStore.framework in Frameworks */,
B52977E11B120F8A003D50A5 /* CoreLocation.framework in Frameworks */,
B52977DF1B120F83003D50A5 /* MapKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
B50132222344E20B00FC238B /* SwiftUI Demo */ = {
isa = PBXGroup;
children = (
B50132232344E24300FC238B /* SwiftUIView.swift */,
B50132272344E5E900FC238B /* SwiftUIContainerViewController.swift */,
);
path = "SwiftUI Demo";
sourceTree = "<group>";
};
B503FADA1AFDC71700F90881 /* List and Object Observers Demo */ = {
isa = PBXGroup;
children = (
B5AA37EE2357D30300FFD4B9 /* ColorsDemo.swift */,
B52977D81B120B80003D50A5 /* ObserversViewController.swift */,
B503FADB1AFDC71700F90881 /* ListObserverDemoViewController.swift */,
B5635D182357F9F700B80E6B /* CollectionViewDemoViewController.swift */,
B503FADC1AFDC71700F90881 /* ObjectObserverDemoViewController.swift */,
B503FADD1AFDC71700F90881 /* Palette.swift */,
B503FADE1AFDC71700F90881 /* PaletteTableViewCell.swift */,
B5635D1A2357FA4B00B80E6B /* PaletteCollectionViewCell.swift */,
B5C37EE42357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift */,
);
path = "List and Object Observers Demo";
sourceTree = "<group>";
};
B52977DB1B120F2C003D50A5 /* Transactions Demo */ = {
isa = PBXGroup;
children = (
B52977E31B121635003D50A5 /* Place.swift */,
B52977DC1B120F3B003D50A5 /* TransactionsDemoViewController.swift */,
);
path = "Transactions Demo";
sourceTree = "<group>";
};
B52977E21B120F90003D50A5 /* Frameworks */ = {
isa = PBXGroup;
children = (
B501323423477D2300FC238B /* SwiftUI.framework */,
B52977E01B120F8A003D50A5 /* CoreLocation.framework */,
B5BDC9211C202429008147CD /* CoreStore.framework */,
B52977DE1B120F83003D50A5 /* MapKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
B54AAD401AF4D26E00848AE0 = {
isa = PBXGroup;
children = (
B52977E21B120F90003D50A5 /* Frameworks */,
B54AAD4B1AF4D26E00848AE0 /* LegacyDemo */,
B54AAD4A1AF4D26E00848AE0 /* Products */,
);
sourceTree = "<group>";
};
B54AAD4A1AF4D26E00848AE0 /* Products */ = {
isa = PBXGroup;
children = (
B54AAD491AF4D26E00848AE0 /* LegacyDemo.app */,
);
name = Products;
sourceTree = "<group>";
};
B54AAD4B1AF4D26E00848AE0 /* LegacyDemo */ = {
isa = PBXGroup;
children = (
B54AAD4E1AF4D26E00848AE0 /* AppDelegate.swift */,
B50132222344E20B00FC238B /* SwiftUI Demo */,
B566E3271B117AE700F4F0C6 /* Stack Setup Demo */,
B503FADA1AFDC71700F90881 /* List and Object Observers Demo */,
B52977DB1B120F2C003D50A5 /* Transactions Demo */,
B56965091B2B35370075EE4A /* Fetching and Querying Demo */,
B569652F1B3591460075EE4A /* Migrations Demo */,
B56964C61B20AC200075EE4A /* Loggers Demo */,
B54AAD571AF4D26E00848AE0 /* Main.storyboard */,
B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */,
B54AAD5C1AF4D26E00848AE0 /* LaunchScreen.xib */,
B54AAD501AF4D26E00848AE0 /* LegacyDemo.xcdatamodeld */,
B56964D51B231AE90075EE4A /* StackSetupDemo.xcdatamodeld */,
B56965271B3582D30075EE4A /* MigrationDemo.xcdatamodeld */,
B54AAD4C1AF4D26E00848AE0 /* Supporting Files */,
);
path = LegacyDemo;
sourceTree = "<group>";
};
B54AAD4C1AF4D26E00848AE0 /* Supporting Files */ = {
isa = PBXGroup;
children = (
B54AAD4D1AF4D26E00848AE0 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
B566E3271B117AE700F4F0C6 /* Stack Setup Demo */ = {
isa = PBXGroup;
children = (
B56964DB1B231BCB0075EE4A /* FemaleAccount.swift */,
B56964D91B231BCA0075EE4A /* MaleAccount.swift */,
B566E3311B11DF3200F4F0C6 /* UserAccount.swift */,
B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */,
);
path = "Stack Setup Demo";
sourceTree = "<group>";
};
B56964C61B20AC200075EE4A /* Loggers Demo */ = {
isa = PBXGroup;
children = (
B56964C81B20AC780075EE4A /* CustomLoggerViewController.swift */,
);
path = "Loggers Demo";
sourceTree = "<group>";
};
B56965091B2B35370075EE4A /* Fetching and Querying Demo */ = {
isa = PBXGroup;
children = (
B56965171B2E20CC0075EE4A /* TimeZone.swift */,
B569650B1B2B36E10075EE4A /* FetchingAndQueryingDemoViewController.swift */,
B56965191B30888A0075EE4A /* FetchingResultsViewController.swift */,
B569651B1B30889A0075EE4A /* QueryingResultsViewController.swift */,
);
path = "Fetching and Querying Demo";
sourceTree = "<group>";
};
B569652F1B3591460075EE4A /* Migrations Demo */ = {
isa = PBXGroup;
children = (
B5EE259D1B3EC1B20000406B /* OrganismProtocol.swift */,
B5EE259A1B3EA4890000406B /* OrganismV3.swift */,
B5EE25861B36E2520000406B /* OrganismV2.swift */,
B5EE25841B36E23C0000406B /* OrganismV1.swift */,
B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */,
B5E599311B5240F50084BD5F /* OrganismTableViewCell.swift */,
B5125C111B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel */,
B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */,
B5125C131B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel */,
);
path = "Migrations Demo";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
B54AAD481AF4D26E00848AE0 /* LegacyDemo */ = {
isa = PBXNativeTarget;
buildConfigurationList = B54AAD6D1AF4D26E00848AE0 /* Build configuration list for PBXNativeTarget "LegacyDemo" */;
buildPhases = (
B54AAD451AF4D26E00848AE0 /* Sources */,
B54AAD461AF4D26E00848AE0 /* Frameworks */,
B54AAD471AF4D26E00848AE0 /* Resources */,
B5E89ACF1C52929C003B04A9 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = LegacyDemo;
productName = LegacyDemo;
productReference = B54AAD491AF4D26E00848AE0 /* LegacyDemo.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
B54AAD411AF4D26E00848AE0 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 1200;
ORGANIZATIONNAME = "John Rommel Estropia";
TargetAttributes = {
B54AAD481AF4D26E00848AE0 = {
CreatedOnToolsVersion = 6.3;
DevelopmentTeam = 2JT32EJ5BH;
LastSwiftMigration = 0900;
};
};
};
buildConfigurationList = B54AAD441AF4D26E00848AE0 /* Build configuration list for PBXProject "LegacyDemo" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = B54AAD401AF4D26E00848AE0;
productRefGroup = B54AAD4A1AF4D26E00848AE0 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
B54AAD481AF4D26E00848AE0 /* LegacyDemo */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
B54AAD471AF4D26E00848AE0 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B54AAD591AF4D26E00848AE0 /* Main.storyboard in Resources */,
B54AAD5E1AF4D26E00848AE0 /* LaunchScreen.xib in Resources */,
B54AAD5B1AF4D26E00848AE0 /* Images.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
B54AAD451AF4D26E00848AE0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B56965181B2E20CC0075EE4A /* TimeZone.swift in Sources */,
B5C37EE52357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift in Sources */,
B56965291B3582D30075EE4A /* MigrationDemo.xcdatamodeld in Sources */,
B5E599321B5240F50084BD5F /* OrganismTableViewCell.swift in Sources */,
B5EE25851B36E23C0000406B /* OrganismV1.swift in Sources */,
B52977DD1B120F3B003D50A5 /* TransactionsDemoViewController.swift in Sources */,
B52977E41B121635003D50A5 /* Place.swift in Sources */,
B569650C1B2B36E10075EE4A /* FetchingAndQueryingDemoViewController.swift in Sources */,
B569651A1B30888A0075EE4A /* FetchingResultsViewController.swift in Sources */,
B5EE25871B36E2520000406B /* OrganismV2.swift in Sources */,
B503FAE01AFDC71700F90881 /* ObjectObserverDemoViewController.swift in Sources */,
B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */,
B56964C91B20AC780075EE4A /* CustomLoggerViewController.swift in Sources */,
B5635D192357F9F700B80E6B /* CollectionViewDemoViewController.swift in Sources */,
B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */,
B56964DA1B231BCA0075EE4A /* MaleAccount.swift in Sources */,
B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */,
B54AAD521AF4D26E00848AE0 /* LegacyDemo.xcdatamodeld in Sources */,
B5EE259B1B3EA4890000406B /* OrganismV3.swift in Sources */,
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */,
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */,
B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */,
B503FADF1AFDC71700F90881 /* ListObserverDemoViewController.swift in Sources */,
B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */,
B50132282344E5E900FC238B /* SwiftUIContainerViewController.swift in Sources */,
B5635D1B2357FA4B00B80E6B /* PaletteCollectionViewCell.swift in Sources */,
B56964D71B231AE90075EE4A /* StackSetupDemo.xcdatamodeld in Sources */,
B56964DC1B231BCB0075EE4A /* FemaleAccount.swift in Sources */,
B5AA37EF2357D30300FFD4B9 /* ColorsDemo.swift in Sources */,
B5EE259E1B3EC1B20000406B /* OrganismProtocol.swift in Sources */,
B5EE258C1B36E40D0000406B /* MigrationsDemoViewController.swift in Sources */,
B50132242344E24300FC238B /* SwiftUIView.swift in Sources */,
B569651C1B30889A0075EE4A /* QueryingResultsViewController.swift in Sources */,
B5125C121B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
B54AAD571AF4D26E00848AE0 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
B54AAD581AF4D26E00848AE0 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
B54AAD5C1AF4D26E00848AE0 /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
B54AAD5D1AF4D26E00848AE0 /* Base */,
);
name = LaunchScreen.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
B54AAD6B1AF4D26E00848AE0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
B54AAD6C1AF4D26E00848AE0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 5.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
B54AAD6E1AF4D26E00848AE0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 2JT32EJ5BH;
INFOPLIST_FILE = LegacyDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.legacydemo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
};
name = Debug;
};
B54AAD6F1AF4D26E00848AE0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 2JT32EJ5BH;
INFOPLIST_FILE = LegacyDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.legacydemo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
B54AAD441AF4D26E00848AE0 /* Build configuration list for PBXProject "LegacyDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B54AAD6B1AF4D26E00848AE0 /* Debug */,
B54AAD6C1AF4D26E00848AE0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B54AAD6D1AF4D26E00848AE0 /* Build configuration list for PBXNativeTarget "LegacyDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B54AAD6E1AF4D26E00848AE0 /* Debug */,
B54AAD6F1AF4D26E00848AE0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCVersionGroup section */
B54AAD501AF4D26E00848AE0 /* LegacyDemo.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
B54AAD511AF4D26E00848AE0 /* LegacyDemo.xcdatamodel */,
);
currentVersion = B54AAD511AF4D26E00848AE0 /* LegacyDemo.xcdatamodel */;
path = LegacyDemo.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
B56964D51B231AE90075EE4A /* StackSetupDemo.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
B56964D61B231AE90075EE4A /* StackSetupDemo.xcdatamodel */,
);
currentVersion = B56964D61B231AE90075EE4A /* StackSetupDemo.xcdatamodel */;
path = StackSetupDemo.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
B56965271B3582D30075EE4A /* MigrationDemo.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
B5EE25881B36E2750000406B /* MigrationDemoV3.xcdatamodel */,
B5EE25801B36E1B00000406B /* MigrationDemoV2.xcdatamodel */,
B56965281B3582D30075EE4A /* MigrationDemo.xcdatamodel */,
);
currentVersion = B5EE25881B36E2750000406B /* MigrationDemoV3.xcdatamodel */;
path = MigrationDemo.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
/* End XCVersionGroup section */
};
rootObject = B54AAD411AF4D26E00848AE0 /* Project object */;
}
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:LegacyDemo.xcodeproj">
</FileRef>
</Workspace>
-26
View File
@@ -1,26 +0,0 @@
//
// AppDelegate.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/02.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - AppDelegate
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
// MARK: UIApplicationDelegate
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
return true
}
}
@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright © 2018 John Rommel Estropia. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="440" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="CoreStoreIcon" translatesAutoresizingMaskIntoConstraints="NO" id="q8C-V6-gXH">
<rect key="frame" x="155" y="83" width="170" height="170"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="CoreStore" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="273" width="440" height="57.5"/>
<fontDescription key="fontDescription" name="HelveticaNeue-UltraLight" family="Helvetica Neue" pointSize="50"/>
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
<constraint firstItem="q8C-V6-gXH" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" multiplier="0.7" id="QW6-8Y-w15"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
<constraint firstItem="q8C-V6-gXH" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="fRb-1V-9iD"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="top" secondItem="q8C-V6-gXH" secondAttribute="bottom" constant="20" id="s63-MP-ush"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
<resources>
<image name="CoreStoreIcon" width="170" height="170"/>
</resources>
</document>
File diff suppressed because it is too large Load Diff
@@ -1,319 +0,0 @@
//
// FetchingAndQueryingDemoViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/12.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
private struct Static {
static let timeZonesStack: DataStack = {
let dataStack = DataStack()
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "TimeZoneDemo.sqlite",
configuration: "FetchingAndQueryingDemo",
localStorageOptions: .recreateStoreOnModelMismatch
)
)
_ = try? dataStack.perform(
synchronous: { (transaction) in
try transaction.deleteAll(From<TimeZone>())
for name in NSTimeZone.knownTimeZoneNames {
let rawTimeZone = NSTimeZone(name: name)!
let cachedTimeZone = transaction.create(Into<TimeZone>())
cachedTimeZone.name = rawTimeZone.name
cachedTimeZone.abbreviation = rawTimeZone.abbreviation ?? ""
cachedTimeZone.secondsFromGMT = Int32(rawTimeZone.secondsFromGMT)
cachedTimeZone.hasDaylightSavingTime = rawTimeZone.isDaylightSavingTime
cachedTimeZone.daylightSavingTimeOffset = rawTimeZone.daylightSavingTimeOffset
}
}
)
return dataStack
}()
}
// MARK: - FetchingAndQueryingDemoViewController
class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
// MARK: UIViewController
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if self.didAppearOnce {
return
}
self.didAppearOnce = true
let alert = UIAlertController(
title: "Fetch and Query Demo",
message: "This demo shows how to execute fetches and queries.\n\nEach menu item executes and displays a preconfigured fetch/query.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if let indexPath = sender as? IndexPath {
switch segue.destination {
case let controller as FetchingResultsViewController:
let item = self.fetchingItems[indexPath.row]
controller.set(timeZones: item.fetch(), title: item.title)
case let controller as QueryingResultsViewController:
let item = self.queryingItems[indexPath.row]
controller.set(value: item.query(), title: item.title)
default:
break
}
}
}
// MARK: UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch self.segmentedControl?.selectedSegmentIndex {
case Section.fetching.rawValue?:
return self.fetchingItems.count
case Section.querying.rawValue?:
return self.queryingItems.count
default:
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell")!
switch self.segmentedControl?.selectedSegmentIndex {
case Section.fetching.rawValue?:
cell.textLabel?.text = self.fetchingItems[indexPath.row].title
case Section.querying.rawValue?:
cell.textLabel?.text = self.queryingItems[indexPath.row].title
default:
cell.textLabel?.text = nil
}
return cell
}
// MARK: UITableViewDelegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
switch self.segmentedControl?.selectedSegmentIndex {
case Section.fetching.rawValue?:
self.performSegue(withIdentifier: "FetchingResultsViewController", sender: indexPath)
case Section.querying.rawValue?:
self.performSegue(withIdentifier: "QueryingResultsViewController", sender: indexPath)
default:
break
}
}
// MARK: Private
private enum Section: Int {
case fetching
case querying
}
private let fetchingItems = [
(
title: "All Time Zones",
fetch: { () -> [TimeZone] in
return try! Static.timeZonesStack.fetchAll(
From<TimeZone>()
.orderBy(.ascending(\.name))
)
}
),
(
title: "Time Zones in Asia",
fetch: { () -> [TimeZone] in
return try! Static.timeZonesStack.fetchAll(
From<TimeZone>()
.where(
format: "%K BEGINSWITH[c] %@",
#keyPath(TimeZone.name),
"Asia"
)
.orderBy(.ascending(\.secondsFromGMT))
)
}
),
(
title: "Time Zones in America and Europe",
fetch: { () -> [TimeZone] in
return try! Static.timeZonesStack.fetchAll(
From<TimeZone>()
.where(
format: "%K BEGINSWITH[c] %@ OR %K BEGINSWITH[c] %@",
#keyPath(TimeZone.name),
"America",
#keyPath(TimeZone.name),
"Europe"
)
.orderBy(.ascending(\.secondsFromGMT))
)
}
),
(
title: "All Time Zones Except America",
fetch: { () -> [TimeZone] in
return try! Static.timeZonesStack.fetchAll(
From<TimeZone>()
.where(
format: "%K BEGINSWITH[c] %@",
#keyPath(TimeZone.name),
"America"
)
.orderBy(.ascending(\.secondsFromGMT))
)
}
),
(
title: "Time Zones with Summer Time",
fetch: { () -> [TimeZone] in
return try! Static.timeZonesStack.fetchAll(
From<TimeZone>()
.where(\.hasDaylightSavingTime == true)
.orderBy(.ascending(\.name))
)
}
)
]
private let queryingItems: [(title: String, query: () -> Any)] = [
(
title: "Number of Time Zones",
query: { () -> Any in
return try! Static.timeZonesStack.queryValue(
From<TimeZone>()
.select(NSNumber.self, .count(\.name))
)!
}
),
(
title: "Abbreviation For Tokyo's Time Zone",
query: { () -> Any in
return try! Static.timeZonesStack.queryValue(
From<TimeZone>()
.select(String.self, .attribute(\.abbreviation))
.where(format: "%K ENDSWITH[c] %@", #keyPath(TimeZone.name), "Tokyo")
)!
}
),
(
title: "All Abbreviations",
query: { () -> Any in
return try! Static.timeZonesStack.queryAttributes(
From<TimeZone>()
.select(
NSDictionary.self,
.attribute(\.name),
.attribute(\.abbreviation)
)
.orderBy(.ascending(\.name))
)
}
),
(
title: "Number of Countries per Time Zone",
query: { () -> Any in
return try! Static.timeZonesStack.queryAttributes(
From<TimeZone>()
.select(
NSDictionary.self,
.count(\.abbreviation),
.attribute(\.abbreviation)
)
.groupBy(\.abbreviation)
.orderBy(
.ascending(\.secondsFromGMT),
.ascending(\.name)
)
)
}
),
(
title: "Number of Countries with Summer Time",
query: { () -> Any in
return try! Static.timeZonesStack.queryAttributes(
From<TimeZone>()
.select(
NSDictionary.self,
.count(\.hasDaylightSavingTime, as: "numberOfCountries"),
.attribute(\.hasDaylightSavingTime)
)
.groupBy(\.hasDaylightSavingTime)
.orderBy(
.descending(\.hasDaylightSavingTime),
.ascending(\.name)
)
)
}
)
]
var didAppearOnce = false
@IBOutlet dynamic weak var segmentedControl: UISegmentedControl?
@IBOutlet dynamic weak var tableView: UITableView?
@IBAction dynamic func segmentedControlValueChanged(_ sender: AnyObject?) {
self.tableView?.reloadData()
}
}
@@ -1,68 +0,0 @@
//
// FetchingResultsViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/17.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - FetchingResultsViewController
class FetchingResultsViewController: UITableViewController {
// MARK: Public
func set(timeZones: [TimeZone]?, title: String) {
self.timeZones += timeZones ?? []
self.sectionTitle = title
self.tableView?.reloadData()
}
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 60
self.tableView.rowHeight = UITableView.automaticDimension
}
// MARK: UITableViewDataSource
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.timeZones.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
let timeZone = self.timeZones[indexPath.row]
cell.textLabel?.text = timeZone.name
cell.detailTextLabel?.text = timeZone.abbreviation
return cell
}
// MARK: UITableViewDelegate
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sectionTitle
}
// MARK: Private
var timeZones = [TimeZone]()
var sectionTitle: String?
}
@@ -1,88 +0,0 @@
//
// QueryingResultsViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/17.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
class QueryingResultsViewController: UITableViewController {
// MARK: Public
func set(value: Any?, title: String) {
switch value {
case (let array as [Any])?:
self.values = array.map { (item: Any) -> (title: String, detail: String) in
(
title: String(describing: item),
detail: String(reflecting: type(of: item))
)
}
case let item?:
self.values = [
(
title: String(describing: item),
detail: String(reflecting: type(of: item))
)
]
default:
self.values = []
}
self.sectionTitle = title
self.tableView?.reloadData()
}
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 60
self.tableView.rowHeight = UITableView.automaticDimension
}
// MARK: UITableViewDataSource
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.values.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
let value = self.values[indexPath.row]
cell.textLabel?.text = value.title
cell.detailTextLabel?.text = value.detail
return cell
}
// MARK: UITableViewDelegate
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sectionTitle
}
// MARK: Private
var values: [(title: String, detail: String)] = []
var sectionTitle: String?
}
@@ -1,20 +0,0 @@
//
// TimeZone.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/15.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreData
class TimeZone: NSManagedObject {
@NSManaged var secondsFromGMT: Int32
@NSManaged var abbreviation: String
@NSManaged var hasDaylightSavingTime: Bool
@NSManaged var daylightSavingTimeOffset: Double
@NSManaged var name: String
}
@@ -1,114 +0,0 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-60@3x-1.png",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-76.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-76@2x.png",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Mask + Oval 1 + Oval 1 + Oval 1.png",
"scale" : "1x"
},
{
"idiom" : "car",
"size" : "60x60",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "car",
"filename" : "Icon-60@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

@@ -1,6 +0,0 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -1,21 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "CoreStoreIcon@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

@@ -1,12 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "first.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.
@@ -1,12 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "second.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.
-56
View File
@@ -1,56 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>CoreStore</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>6.3.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>4</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UIStatusBarTintParameters</key>
<dict>
<key>UINavigationBar</key>
<dict>
<key>Style</key>
<string>UIBarStyleDefault</string>
<key>Translucent</key>
<false/>
</dict>
</dict>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="15702" systemVersion="18G1012" minimumToolsVersion="Xcode 7.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
<entity name="Place" representedClassName="LegacyDemo.Place" 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="LegacyDemo.TimeZone" syncable="YES">
<attribute name="abbreviation" optional="YES" attributeType="String" 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" usesScalarValueType="NO" syncable="YES"/>
</entity>
<configuration name="FetchingAndQueryingDemo">
<memberEntity name="TimeZone"/>
</configuration>
<configuration name="TransactionsDemo">
<memberEntity name="Place"/>
</configuration>
<elements>
<element name="Place" positionX="261" positionY="225" width="128" height="103"/>
<element name="TimeZone" positionX="297" positionY="270" width="128" height="120"/>
</elements>
</model>
@@ -1,168 +0,0 @@
//
// CollectionViewDemoViewController.swift
// LegacyDemo
//
// Created by John Estropia on 2019/10/17.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
// MARK: - CollectionViewDemoViewController
final class CollectionViewDemoViewController: UICollectionViewController {
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
let navigationItem = self.navigationItem
navigationItem.leftBarButtonItems = [
self.editButtonItem,
UIBarButtonItem(
barButtonSystemItem: .trash,
target: self,
action: #selector(self.resetBarButtonItemTouched(_:))
)
]
let filterBarButton = UIBarButtonItem(
title: ColorsDemo.filter.rawValue,
style: .plain,
target: self,
action: #selector(self.filterBarButtonItemTouched(_:))
)
navigationItem.rightBarButtonItems = [
UIBarButtonItem(
barButtonSystemItem: .add,
target: self,
action: #selector(self.addBarButtonItemTouched(_:))
),
UIBarButtonItem(
barButtonSystemItem: .refresh,
target: self,
action: #selector(self.shuffleBarButtonItemTouched(_:))
),
filterBarButton
]
self.filterBarButton = filterBarButton
self.dataSource = DiffableDataSource.CollectionViewAdapter<Palette>(
collectionView: self.collectionView,
dataStack: ColorsDemo.stack,
cellProvider: { (collectionView, indexPath, palette) in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PaletteCollectionViewCell", for: indexPath) as! PaletteCollectionViewCell
cell.colorView?.backgroundColor = palette.color
cell.label?.text = palette.colorText
return cell
},
supplementaryViewProvider: { (collectionView, kind, indexPath) in
switch kind {
case UICollectionView.elementKindSectionHeader:
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "PaletteCollectionSectionHeaderView", for: indexPath) as! PaletteCollectionSectionHeaderView
view.label?.text = ColorsDemo.palettes.snapshot.sectionIDs[indexPath.section]
return view
default:
return nil
}
}
)
ColorsDemo.palettes.addObserver(self) { [weak self] (listPublisher) in
guard let self = self else {
return
}
self.filterBarButton?.title = ColorsDemo.filter.rawValue
self.dataSource?.apply(listPublisher.snapshot, animatingDifferences: true)
}
self.dataSource?.apply(ColorsDemo.palettes.snapshot, animatingDifferences: false)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
switch (segue.identifier, segue.destination, sender) {
case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as ObjectPublisher<Palette>):
destinationViewController.setPalette(palette)
default:
break
}
}
// MARK: UICollectionViewDelegate
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.deselectItem(at: indexPath, animated: true)
self.performSegue(
withIdentifier: "ObjectObserverDemoViewController",
sender: ColorsDemo.palettes.snapshot[indexPath]
)
}
// MARK: Private
private var filterBarButton: UIBarButtonItem?
private var dataSource: DiffableDataSource.CollectionViewAdapter<Palette>?
deinit {
ColorsDemo.palettes.removeObserver(self)
}
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
try transaction.deleteAll(From<Palette>())
},
completion: { _ in }
)
}
@IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.filter = ColorsDemo.filter.next()
}
@IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
_ = transaction.create(Into<Palette>())
},
completion: { _ in }
)
}
@IBAction private dynamic func shuffleBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue = Palette.randomHue()
palette.colorName = nil
}
},
completion: { _ in }
)
}
}
@@ -1,88 +0,0 @@
//
// ColorsDemo.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2019/10/17.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreStore
// MARK: - ColorsDemo
struct ColorsDemo {
enum Filter: String {
case all = "All Colors"
case light = "Light Colors"
case dark = "Dark Colors"
func next() -> Filter {
switch self {
case .all: return .light
case .light: return .dark
case .dark: return .all
}
}
func whereClause() -> Where<Palette> {
switch self {
case .all: return .init()
case .light: return (\Palette.$brightness >= 0.9)
case .dark: return (\Palette.$brightness <= 0.4)
}
}
}
static var filter = Filter.all {
didSet {
try! self.palettes.refetch(
From<Palette>()
.sectionBy(\.$colorName)
.where(self.filter.whereClause())
.orderBy(.ascending(\.$hue))
)
}
}
static let stack: DataStack = {
let dataStack = DataStack(
CoreStoreSchema(
modelVersion: "ColorsDemo",
entities: [
Entity<Palette>("Palette"),
],
versionLock: [
"Palette": [0x8c25aa53c7c90a28, 0xa243a34d25f1a3a7, 0x56565b6935b6055a, 0x4f988bb257bf274f]
]
)
)
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "ColorsDemo.sqlite",
localStorageOptions: .recreateStoreOnModelMismatch
)
)
return dataStack
}()
static let palettes: ListPublisher<Palette> = {
return ColorsDemo.stack.publishList(
From<Palette>()
.sectionBy(\.$colorName)
.orderBy(.ascending(\.$hue))
)
}()
}
@@ -1,181 +0,0 @@
//
// ListObserverDemoViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/02.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
// MARK: - ListObserverDemoViewController
final class ListObserverDemoViewController: UITableViewController {
// MARK: - EditableDataSource
final class EditableDataSource: DiffableDataSource.TableViewAdapter<Palette> {
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
switch editingStyle {
case .delete:
let palette = ColorsDemo.palettes.snapshot[indexPath]
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
transaction.delete(palette)
},
completion: { _ in }
)
default:
break
}
}
}
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
let navigationItem = self.navigationItem
navigationItem.leftBarButtonItems = [
self.editButtonItem,
UIBarButtonItem(
barButtonSystemItem: .trash,
target: self,
action: #selector(self.resetBarButtonItemTouched(_:))
)
]
let filterBarButton = UIBarButtonItem(
title: ColorsDemo.filter.rawValue,
style: .plain,
target: self,
action: #selector(self.filterBarButtonItemTouched(_:))
)
navigationItem.rightBarButtonItems = [
UIBarButtonItem(
barButtonSystemItem: .add,
target: self,
action: #selector(self.addBarButtonItemTouched(_:))
),
UIBarButtonItem(
barButtonSystemItem: .refresh,
target: self,
action: #selector(self.shuffleBarButtonItemTouched(_:))
),
filterBarButton
]
self.filterBarButton = filterBarButton
self.dataSource = EditableDataSource(
tableView: self.tableView,
dataStack: ColorsDemo.stack,
cellProvider: { (tableView, indexPath, palette) in
let cell = tableView.dequeueReusableCell(withIdentifier: "PaletteTableViewCell") as! PaletteTableViewCell
cell.colorView?.backgroundColor = palette.color
cell.label?.text = palette.colorText
return cell
}
)
ColorsDemo.palettes.addObserver(self) { [weak self] (listPublisher) in
guard let self = self else {
return
}
self.filterBarButton?.title = ColorsDemo.filter.rawValue
self.dataSource?.apply(listPublisher.snapshot, animatingDifferences: true)
}
self.dataSource?.apply(ColorsDemo.palettes.snapshot, animatingDifferences: false)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
switch (segue.identifier, segue.destination, sender) {
case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as ObjectPublisher<Palette>):
destinationViewController.setPalette(palette)
default:
break
}
}
// MARK: UITableViewDelegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
self.performSegue(
withIdentifier: "ObjectObserverDemoViewController",
sender: ColorsDemo.palettes.snapshot[indexPath]
)
}
// MARK: Private
private var filterBarButton: UIBarButtonItem?
private var dataSource: DiffableDataSource.TableViewAdapter<Palette>?
deinit {
ColorsDemo.palettes.removeObserver(self)
}
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
try transaction.deleteAll(From<Palette>())
},
completion: { _ in }
)
}
@IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.filter = ColorsDemo.filter.next()
}
@IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
_ = transaction.create(Into<Palette>())
},
completion: { _ in }
)
}
@IBAction private dynamic func shuffleBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue = Palette.randomHue()
palette.colorName = nil
}
},
completion: { _ in }
)
}
}
@@ -1,192 +0,0 @@
//
// ObjectObserverDemoViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/06.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
// MARK: - ObjectObserverDemoViewController
class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
func setPalette<O: ObjectRepresentation>(_ newValue: O?) where O.ObjectType == Palette {
guard self.monitor?.object?.objectID() != newValue?.objectID() else {
return
}
if let newValue = newValue {
self.monitor = newValue.asReadOnly(in: ColorsDemo.stack).map(ColorsDemo.stack.monitorObject(_:))
}
else {
self.monitor = nil
}
}
// MARK: NSObject
deinit {
self.monitor?.removeObserver(self)
}
// MARK: UIViewController
required init?(coder aDecoder: NSCoder) {
if let palette = try! ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.$hue))) {
self.monitor = ColorsDemo.stack.monitorObject(palette)
}
else {
_ = try? ColorsDemo.stack.perform(
synchronous: { (transaction) in
_ = transaction.create(Into<Palette>())
}
)
let palette = try! ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.$hue)))!
self.monitor = ColorsDemo.stack.monitorObject(palette)
}
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
self.monitor?.addObserver(self)
if let palette = self.monitor?.object {
self.reloadPaletteInfo(palette, changedKeys: nil)
}
}
// MARK: ObjectObserver
func objectMonitor(_ monitor: ObjectMonitor<Palette>, didUpdateObject object: Palette, changedPersistentKeys: Set<KeyPathString>) {
self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys)
}
func objectMonitor(_ monitor: ObjectMonitor<Palette>, didDeleteObject object: Palette) {
self.navigationItem.rightBarButtonItem?.isEnabled = false
self.colorNameLabel?.alpha = 0.3
self.colorView?.alpha = 0.3
self.hsbLabel?.text = "Deleted"
self.hsbLabel?.textColor = UIColor.red
self.hueSlider?.isEnabled = false
self.saturationSlider?.isEnabled = false
self.brightnessSlider?.isEnabled = false
}
// MARK: Private
var monitor: ObjectMonitor<Palette>?
@IBOutlet weak var colorNameLabel: UILabel?
@IBOutlet weak var colorView: UIView?
@IBOutlet weak var hsbLabel: UILabel?
@IBOutlet weak var dateLabel: UILabel?
@IBOutlet weak var hueSlider: UISlider?
@IBOutlet weak var saturationSlider: UISlider?
@IBOutlet weak var brightnessSlider: UISlider?
@IBAction dynamic func hueSliderValueDidChange(_ sender: AnyObject?) {
let hue = self.hueSlider?.value ?? 0
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
if let palette = transaction.edit(self?.monitor?.object) {
palette.hue = Int(hue)
}
},
completion: { _ in }
)
}
@IBAction dynamic func saturationSliderValueDidChange(_ sender: AnyObject?) {
let saturation = self.saturationSlider?.value ?? 0
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
if let palette = transaction.edit(self?.monitor?.object) {
palette.saturation = saturation
}
},
completion: { _ in }
)
}
@IBAction dynamic func brightnessSliderValueDidChange(_ sender: AnyObject?) {
let brightness = self.brightnessSlider?.value ?? 0
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
if let palette = transaction.edit(self?.monitor?.object) {
palette.brightness = brightness
}
},
completion: { _ in }
)
}
@IBAction dynamic func deleteBarButtonTapped(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
transaction.delete(self?.monitor?.object)
},
completion: { _ in }
)
}
func reloadPaletteInfo(_ palette: Palette, changedKeys: Set<String>?) {
self.colorNameLabel?.text = palette.colorName
let color = palette.color
self.colorNameLabel?.textColor = color
self.colorView?.backgroundColor = color
self.hsbLabel?.text = palette.colorText
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.$hue)) == true {
self.hueSlider?.value = Float(palette.hue)
}
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.$saturation)) == true {
self.saturationSlider?.value = palette.saturation
}
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.$brightness)) == true {
self.brightnessSlider?.value = palette.brightness
}
}
}
@@ -1,59 +0,0 @@
//
// ObserversViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/24.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - ObserversViewController
class ObserversViewController: UIViewController {
// MARK: UIViewController
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alert = UIAlertController(
title: "Observers Demo",
message: "This demo shows how to observe changes to a list of objects. The top and bottom view controllers both observe a single shared \"ListMonitor\" instance.\n\nTap on a row to see how to observe changes made to a single object using a \"ObjectMonitor\".",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
// MARK: Private
@IBOutlet private dynamic weak var toggleTopBarButtonItem: UIBarButtonItem?
@IBOutlet private dynamic weak var toggleBottomBarButtonItem: UIBarButtonItem?
@IBOutlet private dynamic weak var stackView: UIStackView?
@IBOutlet private dynamic weak var topContainerView: UIView?
@IBOutlet private dynamic weak var bottomContainerView: UIView?
@IBAction private dynamic func toggleTopContainerView() {
UIView.animate(withDuration: 0.2) {
self.topContainerView!.isHidden.toggle()
}
self.toggleTopBarButtonItem!.isEnabled = !self.bottomContainerView!.isHidden
self.toggleBottomBarButtonItem!.isEnabled = !self.topContainerView!.isHidden
}
@IBAction private dynamic func toggleBottomContainerView() {
UIView.animate(withDuration: 0.2) {
self.bottomContainerView!.isHidden.toggle()
}
self.toggleTopBarButtonItem!.isEnabled = !self.bottomContainerView!.isHidden
self.toggleBottomBarButtonItem!.isEnabled = !self.topContainerView!.isHidden
}
}
@@ -1,86 +0,0 @@
//
// Palette.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/05.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import UIKit
import CoreData
import CoreStore
// MARK: - Palette
final class Palette: CoreStoreObject {
@Field.Stored(
"hue",
dynamicInitialValue: { Palette.randomHue() }
)
var hue: Int
@Field.Stored("saturation")
var saturation: Float = 1
@Field.Stored(
"brightness",
dynamicInitialValue: { Palette.randomBrightness() }
)
var brightness: Float
@Field.Virtual(
"colorName",
customGetter: { object, field in
if let colorName = field.primitiveValue {
return colorName
}
let colorName: String
switch object.$hue.value {
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"
case 331 ..< 360: colorName = "Upper Reds"
default: colorName = "<Invalid>"
}
field.primitiveValue = colorName
return colorName
}
)
var colorName: String!
static func randomHue() -> Int {
return Int.random(in: 0 ..< 360)
}
static func randomBrightness() -> Float {
return (Float.random(in: 0 ..< 70) + 30) / 100.0
}
}
extension Palette {
var color: UIColor {
return UIColor(
hue: CGFloat(self.hue) / 360.0,
saturation: CGFloat(self.saturation),
brightness: CGFloat(self.brightness),
alpha: 1.0
)
}
var colorText: String {
return "H: \(self.hue)˚, S: \(round(self.saturation * 100.0))%, B: \(round(self.brightness * 100.0))%"
}
}
@@ -1,17 +0,0 @@
//
// PaletteCollectionSectionHeaderView.swift
// LegacyDemo
//
// Created by John Estropia on 2019/10/17.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - PaletteCollectionSectionHeaderView
final class PaletteCollectionSectionHeaderView: UICollectionReusableView {
@IBOutlet weak var label: UILabel?
}
@@ -1,18 +0,0 @@
//
// PaletteCollectionViewCell.swift
// LegacyDemo
//
// Created by John Estropia on 2019/10/17.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - PaletteCollectionViewCell
final class PaletteCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var colorView: UIView?
@IBOutlet weak var label: UILabel?
}
@@ -1,18 +0,0 @@
//
// PaletteTableViewCell.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/05.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - PaletteTableViewCell
final class PaletteTableViewCell: UITableViewCell {
@IBOutlet weak var colorView: UIView?
@IBOutlet weak var label: UILabel?
}
@@ -1,126 +0,0 @@
//
// CustomLoggerViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/05.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
// MARK: - CustomLoggerViewController
class CustomLoggerViewController: UIViewController, CoreStoreLogger {
// MARK: NSObject
let dataStack = DataStack()
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
try! self.dataStack.addStorageAndWait(SQLiteStore(fileName: "emptyStore.sqlite"))
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
CoreStoreDefaults.logger = self
let alert = UIAlertController(
title: "Logger Demo",
message: "This demo shows how to plug-in any logging framework to CoreStore.\n\nThe view controller implements CoreStoreLogger and appends all logs to the text view.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
CoreStoreDefaults.logger = DefaultLogger()
}
// MARK: CoreStoreLogger
func log(level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
DispatchQueue.main.async { [weak self] in
let levelString: String
switch level {
case .trace: levelString = "Trace"
case .notice: levelString = "Notice"
case .warning: levelString = "Warning"
case .fatal: levelString = "Fatal"
}
self?.textView?.insertText("\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Log:\(levelString)] \(message)\n\n")
}
}
func log(error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
DispatchQueue.main.async { [weak self] in
self?.textView?.insertText("\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Error] \(message): \(error)\n\n")
}
}
func assert(_ condition: @autoclosure () -> Bool, message: @autoclosure () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
if condition() {
return
}
let messageString = message()
DispatchQueue.main.async { [weak self] in
self?.textView?.insertText("\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Assert] \(messageString)\n\n")
}
}
// MARK: Private
@IBOutlet dynamic weak var textView: UITextView?
@IBOutlet dynamic weak var segmentedControl: UISegmentedControl?
@IBAction dynamic func segmentedControlValueChanged(_ sender: AnyObject?) {
switch self.segmentedControl?.selectedSegmentIndex {
case 0?:
let request = NSFetchRequest<NSFetchRequestResult>()
Where<NSManagedObject>(true).applyToFetchRequest(request)
Where<NSManagedObject>(false).applyToFetchRequest(request)
case 1?:
_ = try? dataStack.addStorageAndWait(
SQLiteStore(
fileName: "emptyStore.sqlite",
configuration: "invalidStore"
)
)
case 2?:
DispatchQueue.global(qos: .background).async {
_ = try! self.dataStack.fetchOne(From<Place>())
}
default:
return
}
}
}
@@ -1,445 +0,0 @@
//
// MigrationsDemoViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/21.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
// MARK: - MigrationsDemoViewController
class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewDataSource, UITableViewDelegate {
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
if let segmentedControl = self.segmentedControl {
for (index, model) in self.models.enumerated() {
segmentedControl.setTitle(
model.label,
forSegmentAt: index
)
}
}
self.set(dataStack: nil, model: nil, scrollToSelection: false)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alert = UIAlertController(
title: "Migrations Demo",
message: "This demo shows how to run progressive migrations and how to support multiple model versions in a single project.\n\nThe persistent store contains 10000 organisms, which gain/lose properties when the migration evolves/devolves them.\n\nYou can use the \"mutate\" button to change an organism's properties then migrate to a different model to see how its value gets affected.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
let modelMetadata = withExtendedLifetime(DataStack(xcodeModelName: "MigrationDemo")) {
(dataStack: DataStack) -> ModelMetadata in
let models = self.models
let migrations = try! dataStack.requiredMigrationsForStorage(
SQLiteStore(fileName: "MigrationDemo.sqlite")
)
guard let storeVersion = migrations.first?.sourceVersion else {
return models.first!
}
for model in models {
if model.schemaHistory.currentModelVersion == storeVersion {
return model
}
}
return models.first!
}
self.selectModelVersion(modelMetadata)
}
// MARK: ListObserver
func listMonitorWillChange(_ monitor: ListMonitor<NSManagedObject>) { }
func listMonitorDidChange(_ monitor: ListMonitor<NSManagedObject>) {
if self.lastSelectedIndexPath == nil,
let numberOfObjectsInSection = self.listMonitor?.numberOfObjects(in: 0),
numberOfObjectsInSection > 0 {
self.tableView?.reloadData()
self.setSelectedIndexPath(IndexPath(row: 0, section: 0), scrollToSelection: false)
}
else {
self.updateDisplay(reloadData: true, scrollToSelection: true, animated: true)
}
}
func listMonitorDidRefetch(_ monitor: ListMonitor<NSManagedObject>) {
self.listMonitorDidChange(monitor)
}
// MARK: UITableViewDataSource
@objc dynamic func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.listMonitor?.numberOfObjects(in: 0) ?? 0
}
@objc dynamic func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "OrganismTableViewCell", for: indexPath) as! OrganismTableViewCell
let dna = (self.listMonitor?[indexPath] as? OrganismProtocol)?.dna.description ?? ""
cell.dnaLabel?.text = "DNA: \(dna)"
cell.mutateButtonHandler = { [weak self] () -> Void in
guard let `self` = self,
let dataStack = self.dataStack,
let organism = self.listMonitor?[indexPath] else {
return
}
self.setSelectedIndexPath(indexPath, scrollToSelection: false)
self.setEnabled(false)
dataStack.perform(
asynchronous: { (transaction) in
let organism = transaction.edit(organism) as! OrganismProtocol
organism.mutate()
},
completion: { [weak self] _ in
self?.setEnabled(true)
}
)
}
return cell
}
// MARK: UITableViewDelegate
@objc dynamic func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.setSelectedIndexPath(indexPath, scrollToSelection: false)
}
// MARK: Private
private typealias ModelMetadata = (label: String, entityType: NSManagedObject.Type, schemaHistory: SchemaHistory)
private let models: [ModelMetadata] = [
(
label: "Model V1",
entityType: OrganismV1.self,
schemaHistory: SchemaHistory(
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
),
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
)
),
(
label: "Model V2",
entityType: OrganismV2.self,
schemaHistory: SchemaHistory(
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: [
"MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
]
),
migrationChain: [
"MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
]
)
),
(
label: "Model V3",
entityType: OrganismV3.self,
schemaHistory: SchemaHistory(
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
),
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
)
)
]
private var _listMonitor: ListMonitor<NSManagedObject>?
private var listMonitor: ListMonitor<NSManagedObject>? {
return self._listMonitor
}
private var _dataStack: DataStack?
private var dataStack: DataStack? {
return self._dataStack
}
private var _lastSelectedIndexPath: IndexPath?
private var lastSelectedIndexPath: IndexPath? {
return self._lastSelectedIndexPath
}
private func setSelectedIndexPath(_ indexPath: IndexPath, scrollToSelection: Bool) {
self._lastSelectedIndexPath = indexPath
self.updateDisplay(reloadData: false, scrollToSelection: scrollToSelection, animated: true)
}
@IBOutlet private dynamic weak var headerContainer: UIView?
@IBOutlet private dynamic weak var titleLabel: UILabel?
@IBOutlet private dynamic weak var organismLabel: UILabel?
@IBOutlet private dynamic weak var segmentedControl: UISegmentedControl?
@IBOutlet private dynamic weak var progressView: UIProgressView?
@IBOutlet private dynamic weak var tableView: UITableView?
@IBAction private dynamic func segmentedControlValueChanged(_ sender: AnyObject?) {
guard let index = self.segmentedControl?.selectedSegmentIndex else {
return
}
self.selectModelVersion(self.models[index])
}
private func selectModelVersion(_ model: ModelMetadata) {
if self.dataStack?.modelVersion == model.schemaHistory.currentModelVersion {
return
}
self.set(dataStack: nil, model: nil, scrollToSelection: false) // explicitly trigger NSPersistentStore cleanup by deallocating the stack
let dataStack = DataStack(schemaHistory: model.schemaHistory)
self.setEnabled(false)
let progress = dataStack.addStorage(
SQLiteStore(
fileName: "MigrationDemo.sqlite",
migrationMappingProviders: [
CustomSchemaMappingProvider(
from: "MigrationDemoV3",
to: "MigrationDemoV2",
entityMappings: [
.transformEntity(
sourceEntity: "Organism",
destinationEntity: "Organism",
transformer: { (source, createDestination) in
let destination = createDestination()
destination.enumerateAttributes { (attribute, sourceAttribute) in
if let sourceAttribute = sourceAttribute {
destination[attribute] = source[sourceAttribute]
}
}
destination["numberOfFlippers"] = source["numberOfLimbs"]
}
)
]
)
]
),
completion: { [weak self] (result) -> Void in
guard let `self` = self else {
return
}
guard case .success = result else {
self.setEnabled(true)
return
}
self.set(dataStack: dataStack, model: model, scrollToSelection: true)
let count = try! dataStack.queryValue(
From<NSManagedObject>(model.entityType)
.select(Int.self, .count(#keyPath(OrganismV1.dna))))!
if count > 0 {
self.setEnabled(true)
}
else {
for i: Int64 in 0 ..< 20 {
dataStack.perform(
asynchronous: { (transaction) in
for j: Int64 in 0 ..< 500 {
let organism = transaction.create(Into(model.entityType)) as! OrganismProtocol
organism.dna = (i * 500) + j + 1
organism.mutate()
}
},
completion: { _ in }
)
}
dataStack.perform(
asynchronous: { _ in },
completion: { [weak self] _ in
self?.setEnabled(true)
}
)
}
}
)
if let progress = progress {
progress.setProgressHandler { [weak self] (progress) -> Void in
self?.reloadTableHeaderWithProgress(progress)
}
}
}
private func setEnabled(_ enabled: Bool) {
UIView.animate(
withDuration: 0.2,
delay: 0,
options: .beginFromCurrentState,
animations: { () -> Void in
let navigationItem = self.navigationItem
navigationItem.leftBarButtonItem?.isEnabled = enabled
navigationItem.rightBarButtonItem?.isEnabled = enabled
navigationItem.hidesBackButton = !enabled
self.segmentedControl?.isEnabled = enabled
if let tableView = self.tableView {
tableView.alpha = enabled ? 1.0 : 0.5
tableView.isUserInteractionEnabled = enabled
}
},
completion: nil
)
}
private func set(dataStack: DataStack?, model: ModelMetadata?, scrollToSelection: Bool) {
if let dataStack = dataStack, let model = model {
self.segmentedControl?.selectedSegmentIndex = self.models
.firstIndex(
where: { (arg) -> Bool in
let (_, _, schemaHistory) = arg
return schemaHistory.currentModelVersion == model.schemaHistory.currentModelVersion
}
)!
self._dataStack = dataStack
let listMonitor = dataStack.monitorList(
From(model.entityType),
OrderBy<NSManagedObject>(.descending(#keyPath(OrganismV1.dna)))
)
listMonitor.addObserver(self)
self._listMonitor = listMonitor
if self.lastSelectedIndexPath == nil {
if listMonitor.numberOfObjects(in: 0) > 0 {
self.setSelectedIndexPath(IndexPath(row: 0, section: 0), scrollToSelection: true)
}
}
}
else {
self.segmentedControl?.selectedSegmentIndex = UISegmentedControl.noSegment
self._listMonitor = nil
self._dataStack = nil
}
self.updateDisplay(reloadData: true, scrollToSelection: scrollToSelection, animated: false)
}
private func reloadTableHeaderWithProgress(_ progress: Progress) {
self.progressView?.setProgress(Float(progress.fractionCompleted), animated: true)
self.titleLabel?.text = "Migrating: \(progress.localizedDescription ?? "")"
self.organismLabel?.text = "Progressive step \(progress.localizedAdditionalDescription ?? "")"
}
private func updateDisplay(reloadData: Bool, scrollToSelection: Bool, animated: Bool) {
var lines = [String]()
var organismType = ""
if let indexPath = self.lastSelectedIndexPath, let organism = self.listMonitor?[indexPath] {
for property in organism.entity.properties {
let value = organism.value(forKey: property.name) ?? NSNull()
lines.append("\(property.name): \(value)")
}
organismType = organism.entity.managedObjectClassName
}
self.titleLabel?.text = organismType
self.organismLabel?.text = lines.joined(separator: "\n")
self.progressView?.progress = 0
self.headerContainer?.setNeedsLayout()
guard let tableView = self.tableView else {
return
}
if reloadData {
tableView.reloadData()
}
tableView.layoutIfNeeded()
if let indexPath = self.lastSelectedIndexPath,
indexPath.row < tableView.numberOfRows(inSection: 0) {
tableView.selectRow(at: indexPath,
animated: scrollToSelection && animated,
scrollPosition: scrollToSelection ? .middle : .none
)
}
}
}
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>
@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="8166.2" systemVersion="14E46" minimumToolsVersion="Xcode 7.0">
<elements/>
</model>
@@ -1,16 +0,0 @@
//
// OrganismProtocol.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/27.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
protocol OrganismProtocol: AnyObject {
var dna: Int64 { get set }
func mutate()
}
@@ -1,22 +0,0 @@
//
// OrganismTableViewCell.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/07/12.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
class OrganismTableViewCell: UITableViewCell {
@IBOutlet weak dynamic var dnaLabel: UILabel?
@IBOutlet weak dynamic var mutateButton: UIButton?
var mutateButtonHandler: (() -> Void)?
@IBAction dynamic func mutateButtonTouchUpInside(_ sender: UIButton?) {
self.mutateButtonHandler?()
}
}
@@ -1,25 +0,0 @@
//
// OrganismV1.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/21.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreData
class OrganismV1: NSManagedObject, OrganismProtocol {
@NSManaged var dna: Int64
@NSManaged var hasHead: Bool
@NSManaged var hasTail: Bool
// MARK: OrganismProtocol
func mutate() {
self.hasHead = arc4random_uniform(2) == 1
self.hasTail = arc4random_uniform(2) == 1
}
}
@@ -1,27 +0,0 @@
//
// OrganismV2.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/21.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreData
class OrganismV2: NSManagedObject, OrganismProtocol {
@NSManaged var dna: Int64
@NSManaged var hasHead: Bool
@NSManaged var hasTail: Bool
@NSManaged var numberOfFlippers: Int32
// MARK: OrganismProtocol
func mutate() {
self.hasHead = arc4random_uniform(2) == 1
self.hasTail = arc4random_uniform(2) == 1
self.numberOfFlippers = Int32(arc4random_uniform(9) / 2 * 2)
}
}
File diff suppressed because one or more lines are too long
@@ -1,29 +0,0 @@
//
// OrganismV2ToV3MigrationPolicy.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/27.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import CoreData
class OrganismV2ToV3MigrationPolicy: NSEntityMigrationPolicy {
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager)
for dInstance in manager.destinationInstances(forEntityMappingName: mapping.name, sourceInstances: [sInstance]) {
dInstance.setValue(
false,
forKey: #keyPath(OrganismV3.hasVertebrae)
)
dInstance.setValue(
sInstance.value(forKey: #keyPath(OrganismV2.numberOfFlippers)),
forKey: #keyPath(OrganismV3.numberOfLimbs)
)
}
}
}
@@ -1,29 +0,0 @@
//
// OrganismV3.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/27.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreData
class OrganismV3: NSManagedObject, OrganismProtocol {
@NSManaged var dna: Int64
@NSManaged var hasHead: Bool
@NSManaged var hasTail: Bool
@NSManaged var numberOfLimbs: Int32
@NSManaged var hasVertebrae: Bool
// MARK: OrganismProtocol
func mutate() {
self.hasHead = arc4random_uniform(2) == 1
self.hasTail = arc4random_uniform(2) == 1
self.numberOfLimbs = Int32(arc4random_uniform(9) / 2 * 2)
self.hasVertebrae = arc4random_uniform(2) == 1
}
}
File diff suppressed because one or more lines are too long
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>MigrationDemoV3.xcdatamodel</string>
</dict>
</plist>
@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="11198.3" systemVersion="15F34" minimumToolsVersion="Xcode 4.3" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Organism" representedClassName="LegacyDemo.OrganismV1" syncable="YES">
<attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasHead" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasTail" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
</entity>
<elements>
<element name="Organism" positionX="-36" positionY="9" width="128" height="90"/>
</elements>
</model>
@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="11198.3" systemVersion="15F34" minimumToolsVersion="Xcode 4.3" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Organism" representedClassName="LegacyDemo.OrganismV2" syncable="YES">
<attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasHead" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasTail" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="numberOfFlippers" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
</entity>
<elements>
<element name="Organism" positionX="-36" positionY="9" width="128" height="105"/>
</elements>
</model>
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="12141" systemVersion="16E195" minimumToolsVersion="Xcode 4.3" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Organism" representedClassName="LegacyDemo.OrganismV3" syncable="YES">
<attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasHead" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasTail" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasVertebrae" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="numberOfLimbs" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" elementID="numberOfFlippers" syncable="YES"/>
</entity>
<elements>
<element name="Organism" positionX="-36" positionY="9" width="128" height="120"/>
</elements>
</model>
@@ -1,15 +0,0 @@
//
// FemaleAccount.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/06.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreData
class FemaleAccount: UserAccount {
}
@@ -1,15 +0,0 @@
//
// MaleAccount.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/06.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreData
class MaleAccount: UserAccount {
}
@@ -1,196 +0,0 @@
//
// StackSetupDemoViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/24.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
private struct Static {
static let maleConfiguration = "MaleAccounts"
static let femaleConfiguration = "FemaleAccounts"
static let facebookStack: DataStack = {
let dataStack = DataStack(xcodeModelName: "StackSetupDemo")
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "AccountsDemo_FB_Male.sqlite",
configuration: maleConfiguration,
localStorageOptions: .recreateStoreOnModelMismatch
)
)
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "AccountsDemo_FB_Female.sqlite",
configuration: femaleConfiguration,
localStorageOptions: .recreateStoreOnModelMismatch
)
)
_ = try? dataStack.perform(
synchronous: { (transaction) in
try transaction.deleteAll(From<UserAccount>())
let account1 = transaction.create(Into<MaleAccount>(maleConfiguration))
account1.accountType = "Facebook"
account1.name = "John Smith HCD"
account1.friends = 42
let account2 = transaction.create(Into<FemaleAccount>(femaleConfiguration))
account2.accountType = "Facebook"
account2.name = "Jane Doe HCD"
account2.friends = 314
}
)
return dataStack
}()
static let twitterStack: DataStack = {
let dataStack = DataStack(xcodeModelName: "StackSetupDemo")
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "AccountsDemo_TW_Male.sqlite",
configuration: maleConfiguration,
localStorageOptions: .recreateStoreOnModelMismatch
)
)
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "AccountsDemo_TW_Female.sqlite",
configuration: femaleConfiguration,
localStorageOptions: .recreateStoreOnModelMismatch
)
)
_ = try? dataStack.perform(
synchronous: { (transaction) in
try transaction.deleteAll(From<UserAccount>())
let account1 = transaction.create(Into<MaleAccount>(maleConfiguration))
account1.accountType = "Twitter"
account1.name = "#johnsmith_hcd"
account1.friends = 7
let account2 = transaction.create(Into<FemaleAccount>(femaleConfiguration))
account2.accountType = "Twitter"
account2.name = "#janedoe_hcd"
account2.friends = 100
}
)
return dataStack
}()
}
// MARK: - StackSetupDemoViewController
class StackSetupDemoViewController: UITableViewController {
let accounts = [
try! Static.facebookStack.fetchAll(From<UserAccount>()),
try! Static.twitterStack.fetchAll(From<UserAccount>())
]
// MARK: UIViewController
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tableView.reloadData()
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
self.updateDetails(account: self.accounts[indexPath.section][indexPath.row])
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alert = UIAlertController(
title: "Setup Demo",
message: "This demo shows how to initialize 2 DataStacks with 2 configurations each, for a total of 4 SQLite files, each with 1 instance of a \"UserAccount\" entity.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
// MARK: UITableViewDataSource
override func numberOfSections(in tableView: UITableView) -> Int {
return self.accounts.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.accounts[section].count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell")!
let account = self.accounts[indexPath.section][indexPath.row]
cell.textLabel?.text = account.name
cell.detailTextLabel?.text = "\(account.friends) friends"
return cell
}
// MARK: UITableViewDelegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let account = self.accounts[indexPath.section][indexPath.row]
self.updateDetails(account: account)
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0:
let count = self.accounts[section].count
return "Facebook Accounts (\(count) users)"
case 1:
let count = self.accounts[section].count
return "Twitter Accounts (\(count) users)"
default:
return nil
}
}
// MARK: Private
@IBOutlet private dynamic weak var accountTypeLabel: UILabel?
@IBOutlet private dynamic weak var nameLabel: UILabel?
@IBOutlet private dynamic weak var friendsLabel: UILabel?
private func updateDetails(account: UserAccount) {
self.accountTypeLabel?.text = account.accountType
self.nameLabel?.text = account.name
self.friendsLabel?.text = "\(account.friends) friends"
}
}
@@ -1,20 +0,0 @@
//
// UserAccount.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/24.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreData
// MARK: - UserAccount
class UserAccount: NSManagedObject {
@NSManaged var accountType: String?
@NSManaged var name: String?
@NSManaged var friends: Int32
}
@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="7701" systemVersion="14D136" minimumToolsVersion="Xcode 4.3" macOSVersion="Automatic" iOSVersion="Automatic">
<entity name="FemaleAccount" representedClassName="LegacyDemo.FemaleAccount" parentEntity="UserAccount" syncable="YES"/>
<entity name="MaleAccount" representedClassName="LegacyDemo.MaleAccount" parentEntity="UserAccount" syncable="YES"/>
<entity name="UserAccount" representedClassName="LegacyDemo.UserAccount" isAbstract="YES" syncable="YES">
<attribute name="accountType" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="friends" optional="YES" attributeType="Integer 32" defaultValueString="0" syncable="YES"/>
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
</entity>
<configuration name="FemaleAccounts">
<memberEntity name="FemaleAccount"/>
<memberEntity name="UserAccount"/>
</configuration>
<configuration name="MaleAccounts">
<memberEntity name="MaleAccount"/>
<memberEntity name="UserAccount"/>
</configuration>
<elements>
<element name="UserAccount" positionX="-63" positionY="-18" width="128" height="90"/>
<element name="MaleAccount" positionX="-54" positionY="18" width="128" height="45"/>
<element name="FemaleAccount" positionX="-36" positionY="27" width="128" height="45"/>
</elements>
</model>
@@ -1,53 +0,0 @@
//
// SwiftUIContainerViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2019/10/02.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
#if canImport(SwiftUI)
import SwiftUI
#endif
#if canImport(Combine)
import Combine
#endif
import Compression
final class SwiftUIContainerViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
#if canImport(SwiftUI) && canImport(Combine)
if #available(iOS 13, *) {
let hostingController = UIHostingController(
rootView: SwiftUIView(
palettes: ColorsDemo.stack.publishList(
From<Palette>()
.sectionBy(\.$colorName)
.orderBy(.ascending(\.$hue))
)
)
.environment(\.dataStack, ColorsDemo.stack)
)
self.addChild(hostingController)
hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
hostingController.view.frame = self.view.bounds.inset(by: self.view.safeAreaInsets)
self.view.addSubview(hostingController.view)
hostingController.didMove(toParent: self)
}
#endif
}
}
@@ -1,183 +0,0 @@
//
// SwiftUIView.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2019/10/02.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
#if canImport(SwiftUI) && canImport(Combine)
import SwiftUI
import Combine
import CoreStore
@available(iOS 13.0.0, *)
struct SwiftUIView: View {
@Environment(\.dataStack)
var dataStack: DataStack
@ObservedObject
var palettes: ListPublisher<Palette>
var body: some View {
NavigationView {
List {
ForEach(palettes.snapshot.sectionIDs, id: \.self) { (sectionID) in
Section(header: Text(sectionID)) {
ForEach(self.palettes.snapshot.items(inSectionWithID: sectionID), id: \.self) { palette in
NavigationLink(
destination: DetailView(palette: palette),
label: { ColorCell(palette: palette) }
)
}
.onDelete { itemIndices in
let objectIDsToDelete = self.palettes.snapshot.itemIDs(
inSectionWithID: sectionID,
atIndices: itemIndices
)
self.dataStack.perform(
asynchronous: { transaction in
transaction.delete(objectIDs: objectIDsToDelete)
},
completion: { _ in }
)
}
}
}
}
.navigationBarTitle(Text("SwiftUI (\(palettes.snapshot.numberOfItems) objects)"))
.navigationBarItems(
leading: EditButton(),
trailing: HStack {
Button(
action: {
self.dataStack.perform(
asynchronous: { transaction in
for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue = Palette.randomHue()
palette.colorName = nil
}
},
completion: { _ in }
)
},
label: {
Image(systemName: "goforward")
}
)
.frame(width: 30)
Button(
action: {
self.dataStack.perform(
asynchronous: { transaction in
_ = transaction.create(Into<Palette>())
},
completion: { _ in }
)
},
label: {
Image(systemName: "plus")
}
)
.frame(width: 30)
}
)
.alert(
isPresented: $needsShowAlert,
content: {
Alert(
title: Text("SwiftUI Binding Demo"),
message: Text("This demo shows how to bind to ListPublisher and to CoreStoreObject when using SwiftUI"),
dismissButton: .cancel(Text("OK"))
)
}
)
.onAppear {
self.needsShowAlert = true
}
}
}
@State
private var needsShowAlert = false
}
@available(iOS 13.0.0, *)
struct ColorCell: View {
@ObservedObject
var palette: ObjectPublisher<Palette>
var body: some View {
HStack {
Color(palette.color ?? UIColor.clear)
.cornerRadius(5)
.frame(width: 30, height: 30, alignment: .leading)
Text(palette.colorText ?? "<Deleted>")
}
}
}
@available(iOS 13.0.0, *)
struct DetailView: View {
@Environment(\.dataStack)
var dataStack: DataStack
@ObservedObject
var palette: ObjectPublisher<Palette>
@State var hue: Float = 0
@State var saturation: Float = 0
@State var brightness: Float = 0
init(palette: ObjectPublisher<Palette>) {
self.palette = palette
self.hue = Float(palette.hue ?? 0)
self.saturation = palette.saturation ?? 0
self.brightness = palette.brightness ?? 0
}
var body: some View {
ZStack {
Color(palette.color ?? UIColor.clear)
.cornerRadius(20)
.padding(20)
VStack {
Text(palette.colorText ?? "<Deleted>")
.navigationBarTitle(Text("Color"))
Slider(value: $hue, in: 0.0 ... 359.0 as ClosedRange<Float>)
Slider(value: $saturation, in: 0.0 ... 1.0 as ClosedRange<Float>)
Slider(value: $brightness, in: 0.0 ... 0.1 as ClosedRange<Float>)
}
}
}
}
@available(iOS 13.0.0, *)
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
SwiftUIView(
palettes: ColorsDemo.stack.publishList(
From<Palette>()
.sectionBy(\.$colorName)
.orderBy(.ascending(\.$hue))
)
)
.environment(\.dataStack, ColorsDemo.stack)
}
}
#endif
@@ -1,50 +0,0 @@
//
// Place.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/24.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreData
import MapKit
// MARK: - Place
class Place: NSManagedObject, MKAnnotation {
@NSManaged var latitude: Double
@NSManaged var longitude: Double
@NSManaged var title: String?
@NSManaged var subtitle: String?
func setInitialValues() {
self.latitude = Double(arc4random_uniform(180)) - 90
self.longitude = Double(arc4random_uniform(360)) - 180
self.title = "\(self.latitude), \(self.longitude)"
self.subtitle = nil
}
// MARK: MKAnnotation
var coordinate: CLLocationCoordinate2D {
get {
return CLLocationCoordinate2DMake(
self.latitude,
self.longitude
)
}
set {
self.latitude = newValue.latitude
self.longitude = newValue.longitude
self.title = "\(self.latitude), \(self.longitude)"
self.subtitle = nil
}
}
}
@@ -1,233 +0,0 @@
//
// TransactionsDemoViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/24.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
import Contacts
import CoreLocation
import MapKit
import AddressBookUI
import CoreStore
private struct Static {
static let dataStack = DataStack()
static let placeController: ObjectMonitor<Place> = {
try! Static.dataStack.addStorageAndWait(
SQLiteStore(
fileName: "PlaceDemo.sqlite",
configuration: "TransactionsDemo",
localStorageOptions: .recreateStoreOnModelMismatch
)
)
var place = try! Static.dataStack.fetchOne(From<Place>())
if place == nil {
_ = try? Static.dataStack.perform(
synchronous: { (transaction) in
let place = transaction.create(Into<Place>())
place.setInitialValues()
}
)
place = try! Static.dataStack.fetchOne(From<Place>())
}
return Static.dataStack.monitorObject(place!)
}()
}
// MARK: - TransactionsDemoViewController
class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, ObjectObserver {
// MARK: NSObject
deinit {
Static.placeController.removeObserver(self)
}
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
let longPressGesture = UILongPressGestureRecognizer(
target: self,
action: #selector(self.longPressGestureRecognized(_:))
)
self.mapView?.addGestureRecognizer(longPressGesture)
Static.placeController.addObserver(self)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .refresh,
target: self,
action: #selector(self.refreshButtonTapped(_:))
)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alert = UIAlertController(
title: "Transactions Demo",
message: "This demo shows how to use the 3 types of transactions to save updates: synchronous, asynchronous, and unsafe.\n\nTap and hold on the map to change the pin location.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let mapView = self.mapView, let place = Static.placeController.object {
mapView.addAnnotation(place)
mapView.setCenter(place.coordinate, animated: false)
mapView.selectAnnotation(place, animated: false)
}
}
// MARK: MKMapViewDelegate
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "MKAnnotationView"
var annotationView: MKPinAnnotationView! = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView.isEnabled = true
annotationView.canShowCallout = true
annotationView.animatesDrop = true
}
else {
annotationView.annotation = annotation
}
return annotationView
}
// MARK: ObjectObserver
func objectMonitor(_ monitor: ObjectMonitor<Place>, willUpdateObject object: Place) {
// none
}
func objectMonitor(_ monitor: ObjectMonitor<Place>, didUpdateObject object: Place, changedPersistentKeys: Set<KeyPathString>) {
if let mapView = self.mapView {
mapView.removeAnnotations(mapView.annotations)
mapView.addAnnotation(object)
mapView.setCenter(object.coordinate, animated: true)
mapView.selectAnnotation(object, animated: true)
if changedPersistentKeys.contains(#keyPath(Place.latitude)) || changedPersistentKeys.contains(#keyPath(Place.longitude)) {
self.geocode(place: object)
}
}
}
func objectMonitor(_ monitor: ObjectMonitor<Place>, didDeleteObject object: Place) {
// none
}
// MARK: Private
var geocoder: CLGeocoder?
@IBOutlet weak var mapView: MKMapView?
@IBAction dynamic func longPressGestureRecognized(_ sender: AnyObject?) {
if let mapView = self.mapView,
let gesture = sender as? UILongPressGestureRecognizer,
gesture.state == .began {
let coordinate = mapView.convert(
gesture.location(in: mapView),
toCoordinateFrom: mapView
)
Static.dataStack.perform(
asynchronous: { (transaction) in
let place = transaction.edit(Static.placeController.object)
place?.coordinate = coordinate
},
completion: { _ in }
)
}
}
@IBAction dynamic func refreshButtonTapped(_ sender: AnyObject?) {
_ = try? Static.dataStack.perform(
synchronous: { (transaction) in
let place = transaction.edit(Static.placeController.object)
place?.setInitialValues()
}
)
}
func geocode(place: Place) {
let transaction = Static.dataStack.beginUnsafe()
self.geocoder?.cancelGeocode()
let geocoder = CLGeocoder()
self.geocoder = geocoder
geocoder.reverseGeocodeLocation(
CLLocation(latitude: place.latitude, longitude: place.longitude),
completionHandler: { [weak self] (placemarks, error) -> Void in
if let placemark = placemarks?.first, let dictionary = placemark.addressDictionary {
let place = transaction.edit(Static.placeController.object)
place?.title = placemark.name
place?.subtitle = CNPostalAddressFormatter.string(
from: autoreleasepool {
let address = CNMutablePostalAddress()
(dictionary["Street"] as? String).flatMap({ address.street = $0 })
(dictionary["State"] as? String).flatMap({ address.state = $0 })
(dictionary["City"] as? String).flatMap({ address.city = $0 })
(dictionary["Country"] as? String).flatMap({ address.country = $0 })
(dictionary["ZIP"] as? String).flatMap({ address.postalCode = $0 })
return address
},
style: .mailingAddress
)
transaction.commit { (_) -> Void in }
}
self?.geocoder = nil
}
)
}
}
+1 -2
View File
@@ -45,8 +45,7 @@ let package = Package(
.testTarget( .testTarget(
name: "CoreStoreTests", name: "CoreStoreTests",
dependencies: ["CoreStore"], dependencies: ["CoreStore"],
path: "CoreStoreTests", path: "CoreStoreTests"
exclude: ["BridgingTests.h", "BridgingTests.m"]
) )
], ],
swiftLanguageVersions: [.v5] swiftLanguageVersions: [.v5]
+4 -114
View File
@@ -16,11 +16,12 @@ Unleashing the real power of Core Data with the elegance and safety of Swift
<br /><br />Contact<br /> <br /><br />Contact<br />
<a href="http://swift-corestore-slack.herokuapp.com/"><img alt="Join us on Slack!" src="http://swift-corestore-slack.herokuapp.com/badge.svg?logo=slack" /></a> <a href="http://swift-corestore-slack.herokuapp.com/"><img alt="Join us on Slack!" src="http://swift-corestore-slack.herokuapp.com/badge.svg?logo=slack" /></a>
<a href="https://twitter.com/JohnEstropia"><img alt="Reach me on Twitter!" src="https://img.shields.io/badge/twitter-%40JohnEstropia-3498db.svg?logo=twitter" /></a> <a href="https://twitter.com/JohnEstropia"><img alt="Reach me on Twitter!" src="https://img.shields.io/badge/twitter-%40JohnEstropia-3498db.svg?logo=twitter" /></a>
<a href="https://github.com/sponsors/JohnEstropia"><img alt="Sponsor" src="https://img.shields.io/badge/%E2%9D%A4-Sponsor-ff69bf"></a>
<br /> <br />
</p> </p>
* **Swift 5.4:** iOS 11+ / macOS 10.13+ / watchOS 4.0+ / tvOS 11.0+ * **Swift 5.5:** iOS 11+ / macOS 10.13+ / watchOS 4.0+ / tvOS 11.0+
* Previously supported Swift versions: [Swift 3.2](https://github.com/JohnEstropia/CoreStore/tree/4.2.3), [Swift 4.2](https://github.com/JohnEstropia/CoreStore/tree/6.2.1), [Swift 5.0](https://github.com/JohnEstropia/CoreStore/tree/6.3.2), [Swift 5.1](https://github.com/JohnEstropia/CoreStore/tree/7.0.4), [Swift 5.3](https://github.com/JohnEstropia/CoreStore/tree/7.3.1) * Previously supported Swift versions: [Swift 5.4](https://github.com/JohnEstropia/CoreStore/tree/8.0.1), [Swift 5.3](https://github.com/JohnEstropia/CoreStore/tree/7.3.1), [Swift 5.1](https://github.com/JohnEstropia/CoreStore/tree/7.0.4), [Swift 5.0](https://github.com/JohnEstropia/CoreStore/tree/6.3.2), [Swift 4.2](https://github.com/JohnEstropia/CoreStore/tree/6.2.1), [Swift 3.2](https://github.com/JohnEstropia/CoreStore/tree/4.2.3)
Upgrading from previous CoreStore versions? Check out the [🆕 features](#features) and make sure to read the [Change logs](https://github.com/JohnEstropia/CoreStore/releases). Upgrading from previous CoreStore versions? Check out the [🆕 features](#features) and make sure to read the [Change logs](https://github.com/JohnEstropia/CoreStore/releases).
@@ -67,7 +68,6 @@ CoreStore is part of the [Swift Source Compatibility projects](https://swift.org
- [Observe a single object's per-property updates](#observe-a-single-objects-per-property-updates) - [Observe a single object's per-property updates](#observe-a-single-objects-per-property-updates)
- [Observe a diffable list](#observe-a-diffable-list) - [Observe a diffable list](#observe-a-diffable-list)
- [Observe detailed list changes](#observe-detailed-list-changes) - [Observe detailed list changes](#observe-detailed-list-changes)
- [Objective-C support](#objective-c-support)
- [Type-safe `CoreStoreObject`s](#type-safe-corestoreobjects) - [Type-safe `CoreStoreObject`s](#type-safe-corestoreobjects)
- [New `@Field` Property Wrapper syntax](#new-field-property-wrapper-syntax) - [New `@Field` Property Wrapper syntax](#new-field-property-wrapper-syntax)
- [`@Field.Stored` ](#fieldstored) - [`@Field.Stored` ](#fieldstored)
@@ -198,7 +198,6 @@ CoreStore was (and is) heavily shaped by real-world needs of developing data-dep
- **🎯Free to name entities and their class names independently.** CoreStore gets around a restriction with other Core Data wrappers where the entity name should be the same as the `NSManagedObject` subclass name. CoreStore loads entity-to-class mappings from the managed object model file, so you can assign independent names for the entities and their class names. - **🎯Free to name entities and their class names independently.** CoreStore gets around a restriction with other Core Data wrappers where the entity name should be the same as the `NSManagedObject` subclass name. CoreStore loads entity-to-class mappings from the managed object model file, so you can assign independent names for the entities and their class names.
- **📙Full Documentation.** No magic here; all public classes, functions, properties, etc. have detailed *Apple Docs*. This *README* also introduces a lot of concepts and explains a lot of CoreStore's behavior. - **📙Full Documentation.** No magic here; all public classes, functions, properties, etc. have detailed *Apple Docs*. This *README* also introduces a lot of concepts and explains a lot of CoreStore's behavior.
- **️Informative (and pretty) logs.** All CoreStore and Core Data-related types now have very informative and pretty print outputs! *(See [Logging and error reporting](#logging-and-error-reporting))* - **️Informative (and pretty) logs.** All CoreStore and Core Data-related types now have very informative and pretty print outputs! *(See [Logging and error reporting](#logging-and-error-reporting))*
- **🎗Objective-C support!** Is your project transitioning from Objective-C to Swift but still can't quite fully convert some huge classes to Swift yet? CoreStore adjusts to the ever-increasing Swift adoption. While still written in pure Swift, all CoreStore types have their corresponding Objective-C-visible "bridging classes". *(See [Objective-C support](#objective-c-support))*
- **🛡More extensive Unit Tests.** Extending CoreStore is safe without having to worry about breaking old behavior. - **🛡More extensive Unit Tests.** Extending CoreStore is safe without having to worry about breaking old behavior.
*Have ideas that may benefit other Core Data users? [Feature Request](https://github.com/JohnEstropia/CoreStore/issues)s are welcome!* *Have ideas that may benefit other Core Data users? [Feature Request](https://github.com/JohnEstropia/CoreStore/issues)s are welcome!*
@@ -1676,111 +1675,6 @@ let person2 = self.monitor[1, 2]
// person1 and person2 are the same object // person1 and person2 are the same object
``` ```
## Objective-C support
> ⚠️Objective-C support is planned to be deprecated in a future CoreStore version.
All CoreStore types are still written in pure Swift, but most core types have Objective-C "bridging classes" that are visible to Objective-C code. To show a couple of usage examples:
<table>
<tr><th>Swift</th><th>Objective-C</th></tr>
<tr>
<td><pre lang=swift>
try dataStack.addStorageAndWait(SQLiteStore.self)
</pre></td>
<td><pre lang=objc>
NSError *error
[CSCoreStore addSQLiteStorageAndWait:[CSSQLiteStore new] error:&error]
</pre></td>
</tr>
<tr>
<td><pre lang=swift>
dataStack.perform(
asynchronous: { (transaction) in
// ...
},
completion: { (result) in
switch result {
case .success: print("Done")
case .failure(let error): print(error)
}
}
)
</pre></td>
<td><pre lang=objc>
[CSCoreStore beginAsynchronous:^(CSAsynchronousDataTransaction *transaction) {
// ...
[transaction
commitWithSuccess:^{
NSLog(@"Done");
}
failure: ^(CSError *error) {
NSLog(@"error: %@", result.error);
}];
}];
</pre></td>
</tr>
</table>
All of these `CS`-prefixed bridging classes have very similar usage to the existing CoreStore APIs, and ironically *none of them are written in Objective-C*. This is very different to the common approach where apps and libraries write Objective-C APIs just to support both Objective-C and Swift. The advantage with CoreStore's approach is that your Swift codebase can already use the purely-Swift API without further changes in the future, but your "hybrid" codebase can still bridge instances back and forth from Objective-C to Swift.
For example, you may have a new, modern Swift class that holds a `ListMonitor`:
```swift
class MyViewController: UIViewController {
let monitor = dataStack.monitorList(From<MyEntity>(), ...)
// ...
}
```
Now let's say you have a legacy Objective-C class that previously uses `NSFetchedResultsController`. It's easy to switch from `NSFetchedResultsController` to `CSListMonitor`, but converting the rest of this huge class is impractical. You end up with
```objc
@interface MYOldViewController: UIViewController
@property (nonatomic, readonly, strong) CSListMonitor* monitor;
- (instancetype)initWithMonitor:(CSListMonitor *)monitor;
@end
```
When you need to instantiate this class from Swift, you just call `bridgeToObjectiveC`:
```swift
class MyViewController: UIViewController {
let monitor = dataStack.monitorList(From<MyEntity>(), ...)
func showOldController() {
let controller = MYOldViewController(monitor: self.monitor.bridgeToObjectiveC)
self.presentViewController(controller, animated: true, completion: nil)
}
}
```
Note that the `CSListMonitor` holds the exact same `ListMonitor` instance, which means that no copies and no extra fetching occur.
### Objective-C syntax sugars
Objective-C tends to be verbose, so some method calls are long and unreadable. For example, fetching looks like this:
```objc
NSArray<MYPerson *> *objects =
[CSCoreStore
fetchAllFrom:[[CSFrom alloc] initWithEntityClass:[MYPerson class]]
fetchClauses:@[[[CSWhere alloc] initWithFormat:@"%K == %@", @"isHidden", @NO],
[[CSOrderBy alloc] initWithSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"lastName" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"firstName" ascending:YES]]]]];
```
Although it works, it looks terrible. For this, CoreStore provides *CoreStoreBridge.h* where these Objective-C calls are wrapped in readable, convenient macros and global functions. The call above becomes
```objc
NSArray<MYPerson *> *objects =
[CSCoreStore
fetchAllFrom:CSFromClass([MYPerson class])
fetchClauses:@[CSWhereFormat(@"%K == %@", @"isHidden", @NO),
CSOrderByKeys(CSSortAscending(@"lastName"),
CSSortAscending(@"firstName"), nil)]];
```
That's much shorter now. But we can still do better. Notice that we have strings being used as key paths. The `CSKeyPath(...)` macro gives us compile-time checking so keys that don't exist in a class will generate errors. Our key-safe code now looks like this:
```objc
NSArray<MYPerson *> *objects =
[CSCoreStore
fetchAllFrom:CSFromClass([MYPerson class])
fetchClauses:@[CSWhereFormat(@"%K == %@", CSKeyPath(MYPerson, isHidden), @NO),
CSOrderByKeys(CSSortAscending(CSKeyPath(MYPerson, lastName)),
CSSortAscending(CSKeyPath(MYPerson, firstName)), nil)]];
```
To use these syntax sugars, include *CoreStoreBridge.h* in your Objective-C source files.
## Type-safe `CoreStoreObject`s ## Type-safe `CoreStoreObject`s
Starting CoreStore 4.0, we can now create persisted objects without depending on *.xcdatamodeld* Core Data files. The new `CoreStoreObject` subclass replaces `NSManagedObject`, and specially-typed properties declared on these classes will be synthesized as Core Data attributes. Starting CoreStore 4.0, we can now create persisted objects without depending on *.xcdatamodeld* Core Data files. The new `CoreStoreObject` subclass replaces `NSManagedObject`, and specially-typed properties declared on these classes will be synthesized as Core Data attributes.
```swift ```swift
@@ -2593,13 +2487,9 @@ From the **File** - **Swift Packages** - **Add Package Dependency…** menu, sea
``` ```
CoreStore CoreStore
``` ```
where `JohnEstropia` is the *Owner* (forks may appear as well). Then add to your project. where `JohnEstropia` is the *Owner* (forks may appear as well). Then add to your project
### Objective-C support
To use the Objective-C syntax sugars, import *CoreStoreBridge.h* in your *.m* source files.
# Changesets # Changesets
For the full Changelog, refer to the [Releases](https://github.com/JohnEstropia/CoreStore/releases) page. For the full Changelog, refer to the [Releases](https://github.com/JohnEstropia/CoreStore/releases) page.
+20 -7
View File
@@ -158,9 +158,19 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
// MARK: Internal // MARK: Internal
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue) { internal init(
mainContext: NSManagedObjectContext,
queue: DispatchQueue,
sourceIdentifier: Any?
) {
super.init(mainContext: mainContext, queue: queue, supportsUndo: false, bypassesQueueing: false) super.init(
mainContext: mainContext,
queue: queue,
supportsUndo: false,
bypassesQueueing: false,
sourceIdentifier: sourceIdentifier
)
} }
internal func autoCommit(_ completion: @escaping (_ hasChanges: Bool, _ error: CoreStoreError?) -> Void) { internal func autoCommit(_ completion: @escaping (_ hasChanges: Bool, _ error: CoreStoreError?) -> Void) {
@@ -168,12 +178,15 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
self.isCommitted = true self.isCommitted = true
let group = DispatchGroup() let group = DispatchGroup()
group.enter() group.enter()
self.context.saveAsynchronouslyWithCompletion { (hasChanges, error) -> Void in self.context.saveAsynchronously(
sourceIdentifier: self.sourceIdentifier,
completion: { (hasChanges, error) -> Void in
completion(hasChanges, error) completion(hasChanges, error)
self.result = (hasChanges, error) self.result = (hasChanges, error)
group.leave() group.leave()
} }
)
group.wait() group.wait()
self.context.reset() self.context.reset()
} }
+13 -1
View File
@@ -412,6 +412,11 @@ public /*abstract*/ class BaseDataTransaction {
// MARK: 3rd Party Utilities // MARK: 3rd Party Utilities
/**
An arbitrary value that identifies the source of this transaction. Callers of the transaction can provide this value through the `DataStack.perform(...)` methods.
*/
public let sourceIdentifier: Any?
/** /**
Allow external libraries to store custom data in the transaction. App code should rarely have a need for this. Allow external libraries to store custom data in the transaction. App code should rarely have a need for this.
``` ```
@@ -438,7 +443,13 @@ public /*abstract*/ class BaseDataTransaction {
internal var isCommitted = false internal var isCommitted = false
internal var result: (hasChanges: Bool, error: CoreStoreError?)? internal var result: (hasChanges: Bool, error: CoreStoreError?)?
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, supportsUndo: Bool, bypassesQueueing: Bool) { internal init(
mainContext: NSManagedObjectContext,
queue: DispatchQueue,
supportsUndo: Bool,
bypassesQueueing: Bool,
sourceIdentifier: Any?
) {
let context = mainContext.temporaryContextInTransactionWithConcurrencyType( let context = mainContext.temporaryContextInTransactionWithConcurrencyType(
queue == .main queue == .main
@@ -449,6 +460,7 @@ public /*abstract*/ class BaseDataTransaction {
self.context = context self.context = context
self.supportsUndo = supportsUndo self.supportsUndo = supportsUndo
self.bypassesQueueing = bypassesQueueing self.bypassesQueueing = bypassesQueueing
self.sourceIdentifier = sourceIdentifier
context.parentTransaction = self context.parentTransaction = self
context.isTransactionContext = true context.isTransactionContext = true
+12 -75
View File
@@ -29,43 +29,14 @@ import CoreData
// MARK: - CSAsynchronousDataTransaction // MARK: - CSAsynchronousDataTransaction
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSAsynchronousDataTransaction` serves as the Objective-C bridging type for `AsynchronousDataTransaction`.
- SeeAlso: `AsynchronousDataTransaction`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc @objc
public final class CSAsynchronousDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType { public final class CSAsynchronousDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
/**
Saves the transaction changes. This method should not be used after the `-commitWithCompletion:` method was already called once.
- parameter success: the block executed if the save succeeds.
- parameter failure: the block executed if the save fails. A `CSError` is reported as the argument of the block.
*/
@objc @objc
public func commitWithSuccess(_ success: (() -> Void)?, failure: ((CSError) -> Void)?) { public func commitWithSuccess(_ success: (() -> Void)?, failure: ((CSError) -> Void)?) {
Internals.assert( fatalError()
self.bridgeToSwift.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to commit a \(Internals.typeName(self)) outside its designated queue."
)
Internals.assert(
!self.bridgeToSwift.isCommitted,
"Attempted to commit a \(Internals.typeName(self)) more than once."
)
self.bridgeToSwift.autoCommit { (_, error) in
if let error = error {
failure?(error.bridgeToObjectiveC)
}
else {
success?()
}
}
} }
@@ -73,69 +44,40 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction, CoreSto
public override var description: String { public override var description: String {
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)" fatalError()
} }
// MARK: BaseDataTransaction // MARK: BaseDataTransaction
/**
Creates a new `NSManagedObject` with the specified entity type.
- parameter into: the `CSInto` clause indicating the destination `NSManagedObject` entity type and the destination configuration
- returns: a new `NSManagedObject` instance of the specified entity type.
*/
@objc @objc
public override func createInto(_ into: CSInto) -> Any { public override func createInto(_ into: CSInto) -> Any {
return self.bridgeToSwift.create(into.bridgeToSwift) fatalError()
} }
/**
Returns an editable proxy of a specified `NSManagedObject`. This method should not be used after the `-commitWithCompletion:` method was already called once.
- parameter object: the `NSManagedObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@objc @objc
public override func editObject(_ object: NSManagedObject?) -> Any? { public override func editObject(_ object: NSManagedObject?) -> Any? {
return self.bridgeToSwift.edit(object) fatalError()
} }
/**
Returns an editable proxy of the object with the specified `NSManagedObjectID`. This method should not be used after the `-commitWithCompletion:` method was already called once.
- parameter into: a `CSInto` clause specifying the entity type
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@objc @objc
public override func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? { public override func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
return self.bridgeToSwift.edit(into.bridgeToSwift, objectID) fatalError()
} }
/**
Deletes a specified `NSManagedObject`. This method should not be used after the `-commitWithCompletion:` method was already called once.
- parameter object: the `NSManagedObject` type to be deleted
*/
@objc @objc
public override func deleteObject(_ object: NSManagedObject?) { public override func deleteObject(_ object: NSManagedObject?) {
self.bridgeToSwift.delete(object) fatalError()
} }
/**
Deletes the specified `NSManagedObject`s.
- parameter objects: the `NSManagedObject`s type to be deleted
*/
@objc @objc
public override func deleteObjects(_ objects: [NSManagedObject]) { public override func deleteObjects(_ objects: [NSManagedObject]) {
self.bridgeToSwift.delete(objects) fatalError()
} }
@@ -145,30 +87,25 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction, CoreSto
public var bridgeToSwift: AsynchronousDataTransaction { public var bridgeToSwift: AsynchronousDataTransaction {
return super.swiftTransaction as! AsynchronousDataTransaction fatalError()
} }
public required init(_ swiftValue: AsynchronousDataTransaction) { public required init(_ swiftValue: AsynchronousDataTransaction) {
super.init(swiftValue as BaseDataTransaction) fatalError()
}
public required override init(_ swiftValue: BaseDataTransaction) {
super.init(swiftValue)
} }
} }
// MARK: - AsynchronousDataTransaction // MARK: - AsynchronousDataTransaction
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.") @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
extension AsynchronousDataTransaction: CoreStoreSwiftType { extension AsynchronousDataTransaction: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
public var bridgeToObjectiveC: CSAsynchronousDataTransaction { public var bridgeToObjectiveC: CSAsynchronousDataTransaction {
return CSAsynchronousDataTransaction(self) fatalError()
} }
} }
+11 -112
View File
@@ -29,167 +29,66 @@ import CoreData
// MARK: - CSBaseDataTransaction // MARK: - CSBaseDataTransaction
@available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
extension CSBaseDataTransaction { extension CSBaseDataTransaction {
/**
Fetches the `NSManagedObject` instance in the transaction's context from a reference created from a transaction or from a different managed object context.
- parameter object: a reference to the object created/fetched outside the transaction
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/
@objc @objc
public func fetchExistingObject(_ object: NSManagedObject) -> Any? { public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
return self.swiftTransaction.context.fetchExisting(object) as NSManagedObject? fatalError()
} }
/**
Fetches the `NSManagedObject` instance in the transaction's context from an `NSManagedObjectID`.
- parameter objectID: the `NSManagedObjectID` for the object
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/
@objc @objc
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? { public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
return self.swiftTransaction.context.fetchExisting(objectID) as NSManagedObject? fatalError()
} }
/**
Fetches the `NSManagedObject` instances in the transaction's context from references created from a transaction or from a different managed object context.
- parameter objects: an array of `NSManagedObject`s created/fetched outside the transaction
- returns: the `NSManagedObject` array for objects that exists in the transaction
*/
@objc @objc
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] { public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
return self.swiftTransaction.context.fetchExisting(objects) as [NSManagedObject] fatalError()
} }
/**
Fetches the `NSManagedObject` instances in the transaction's context from a list of `NSManagedObjectID`.
- parameter objectIDs: the `NSManagedObjectID` array for the objects
- returns: the `NSManagedObject` array for objects that exists in the transaction
*/
@objc @objc
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] { public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
return self.swiftTransaction.context.fetchExisting(objectIDs) as [NSManagedObject] fatalError()
} }
/**
Fetches the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `CSFetchClause` instances for the fetch request. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s
*/
@objc @objc
public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? { public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
Internals.assert( fatalError()
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return (try? self.swiftTransaction.context.fetchOne(from, fetchClauses))?
.flatMap({ $0 })
} }
/**
Fetches all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter fetchClauses: a series of `CSFetchClause` instances for the fetch request. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s
*/
@objc @objc
public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? { public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
Internals.assert( fatalError()
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return (try? self.swiftTransaction.context.fetchAll(from, fetchClauses))
.flatMap({ $0 })
} }
/**
Fetches the number of `NSManagedObject`s that satisfy the specified `CSFetchClause`s. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter fetchClauses: a series of `CSFetchClause` instances for the fetch request. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- returns: the number `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/
@objc @objc
public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? { public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
Internals.assert( fatalError()
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return (try? self.swiftTransaction.context.fetchCount(from, fetchClauses))
.flatMap({ NSNumber(value: $0) })
} }
/**
Fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter fetchClauses: a series of `CSFetchClause` instances for the fetch request. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s
*/
@objc @objc
public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? { public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
Internals.assert( fatalError()
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return (try? self.swiftTransaction.context.fetchObjectID(from, fetchClauses))
.flatMap({ $0 })
} }
/**
Queries aggregate values as specified by the `CSQueryClause`s. Requires at least a `CSSelect` clause, and optional `CSWhere`, `CSOrderBy`, `CSGroupBy`, and `CSTweak` clauses.
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter selectClause: a `CSSelect` clause indicating the properties to fetch, and with the generic type indicating the return type.
- parameter queryClauses: a series of `CSQueryClause` instances for the query request. Accepts `CSWhere`, `CSOrderBy`, `CSGroupBy`, and `CSTweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/
@objc @objc
public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? { public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
Internals.assert( fatalError()
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
)
return (try? self.swiftTransaction.context.queryValue(from, selectClause, queryClauses))
.flatMap({ $0 })
} }
/**
Queries a dictionary of attribute values as specified by the `CSQueryClause`s. Requires at least a `CSSelect` clause, and optional `CSWhere`, `CSOrderBy`, `CSGroupBy`, and `CSTweak` clauses.
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter selectClause: a `CSSelect` clause indicating the properties to fetch, and with the generic type indicating the return type.
- parameter queryClauses: a series of `CSQueryClause` instances for the query request. Accepts `CSWhere`, `CSOrderBy`, `CSGroupBy`, and `CSTweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/
@objc @objc
public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? { public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
Internals.assert( fatalError()
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
)
return (try? self.swiftTransaction.context.queryAttributes(from, selectClause, queryClauses))
.flatMap({ $0 })
} }
} }
+19 -124
View File
@@ -29,199 +29,109 @@ import CoreData
// MARK: - CSBaseDataTransaction // MARK: - CSBaseDataTransaction
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSBaseDataTransaction` serves as the Objective-C bridging type for `BaseDataTransaction`.
- SeeAlso: `BaseDataTransaction`
*/
@objc @objc
public class CSBaseDataTransaction: NSObject { public class CSBaseDataTransaction: NSObject {
// MARK: Object management // MARK: Object management
/**
Indicates if the transaction has pending changes
*/
@objc @objc
public var hasChanges: Bool { public var hasChanges: Bool {
return self.swiftTransaction.hasChanges fatalError()
} }
/**
Creates a new `NSManagedObject` with the specified entity type.
- parameter into: the `CSInto` clause indicating the destination `NSManagedObject` entity type and the destination configuration
- returns: a new `NSManagedObject` instance of the specified entity type.
*/
@objc @objc
public func createInto(_ into: CSInto) -> Any { public func createInto(_ into: CSInto) -> Any {
return self.swiftTransaction.create(into.bridgeToSwift) fatalError()
} }
/**
Returns an editable proxy of a specified `NSManagedObject`.
- parameter object: the `NSManagedObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@objc @objc
public func editObject(_ object: NSManagedObject?) -> Any? { public func editObject(_ object: NSManagedObject?) -> Any? {
return self.swiftTransaction.edit(object) fatalError()
} }
/**
Returns an editable proxy of the object with the specified `NSManagedObjectID`.
- parameter into: a `CSInto` clause specifying the entity type
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@objc @objc
public func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? { public func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
return self.swiftTransaction.edit(into.bridgeToSwift, objectID) fatalError()
} }
/**
Deletes a specified `NSManagedObject`.
- parameter object: the `NSManagedObject` to be deleted
*/
@objc @objc
public func deleteObject(_ object: NSManagedObject?) { public func deleteObject(_ object: NSManagedObject?) {
self.swiftTransaction.delete(object) fatalError()
} }
/**
Deletes the specified `NSManagedObject`s.
- parameter objects: the `NSManagedObject`s to be deleted
*/
@objc @objc
public func deleteObjects(_ objects: [NSManagedObject]) { public func deleteObjects(_ objects: [NSManagedObject]) {
self.swiftTransaction.delete(objects) fatalError()
} }
/**
Refreshes all registered objects `NSManagedObject`s in the transaction.
*/
@objc @objc
public func refreshAndMergeAllObjects() { public func refreshAndMergeAllObjects() {
self.swiftTransaction.refreshAndMergeAllObjects() fatalError()
} }
// MARK: Inspecting Pending Objects // MARK: Inspecting Pending Objects
/**
Returns all pending `NSManagedObject`s of the specified type that were inserted to the transaction. This method should not be called after the `-commit*:` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were inserted to the transaction.
*/
@objc @objc
public func insertedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> { public func insertedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
return self.swiftTransaction.insertedObjects(entity) fatalError()
} }
/**
Returns all pending `NSManagedObjectID`s that were inserted to the transaction. This method should not be called after the `-commit*:` method was called.
- returns: an `NSSet` of pending `NSManagedObjectID`s that were inserted to the transaction.
*/
@objc @objc
public func insertedObjectIDs() -> Set<NSManagedObjectID> { public func insertedObjectIDs() -> Set<NSManagedObjectID> {
return self.swiftTransaction.insertedObjectIDs() fatalError()
} }
/**
Returns all pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. This method should not be called after the `-commit*:` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction.
*/
@objc @objc
public func insertedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> { public func insertedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
return self.swiftTransaction.insertedObjectIDs(entity) fatalError()
} }
/**
Returns all pending `NSManagedObject`s of the specified type that were updated in the transaction. This method should not be called after the `-commit*:` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were updated in the transaction.
*/
@objc @objc
public func updatedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> { public func updatedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
return self.swiftTransaction.updatedObjects(entity) fatalError()
} }
/**
Returns all pending `NSManagedObjectID`s that were updated in the transaction. This method should not be called after the `-commit*:` method was called.
- returns: an `NSSet` of pending `NSManagedObjectID`s that were updated in the transaction.
*/
@objc @objc
public func updatedObjectIDs() -> Set<NSManagedObjectID> { public func updatedObjectIDs() -> Set<NSManagedObjectID> {
return self.swiftTransaction.updatedObjectIDs() fatalError()
} }
/**
Returns all pending `NSManagedObjectID`s of the specified type that were updated in the transaction. This method should not be called after the `-commit*:` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction.
*/
@objc @objc
public func updatedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> { public func updatedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
return self.swiftTransaction.updatedObjectIDs(entity) fatalError()
} }
/**
Returns all pending `NSManagedObject`s of the specified type that were deleted from the transaction. This method should not be called after the `-commit*:` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were deleted from the transaction.
*/
@objc @objc
public func deletedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> { public func deletedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
return self.swiftTransaction.deletedObjects(entity) fatalError()
} }
/**
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `-commit*:` method was called.
- returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/
@objc @objc
public func deletedObjectIDs() -> Set<NSManagedObjectID> { public func deletedObjectIDs() -> Set<NSManagedObjectID> {
return self.swiftTransaction.deletedObjectIDs() fatalError()
} }
/**
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `-commit*:` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/
@objc @objc
public func deletedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> { public func deletedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
return self.swiftTransaction.deletedObjectIDs(entity) fatalError()
} }
@@ -229,26 +139,11 @@ public class CSBaseDataTransaction: NSObject {
public override var hash: Int { public override var hash: Int {
return ObjectIdentifier(self.swiftTransaction).hashValue fatalError()
} }
public override func isEqual(_ object: Any?) -> Bool { public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSBaseDataTransaction else { fatalError()
return false
}
return self.swiftTransaction === object.swiftTransaction
}
// MARK: Internal
internal let swiftTransaction: BaseDataTransaction
internal init(_ swiftValue: BaseDataTransaction) {
self.swiftTransaction = swiftValue
super.init()
} }
} }
+3 -15
View File
@@ -29,11 +29,7 @@ import CoreData
// MARK: - CSFetchClause // MARK: - CSFetchClause
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSFetchClause` implement clauses used to configure `NSFetchRequest`s.
- SeeAlso: `FetchClause`
*/
@objc @objc
public protocol CSFetchClause { public protocol CSFetchClause {
@@ -44,11 +40,7 @@ public protocol CSFetchClause {
// MARK: - CSQueryClause // MARK: - CSQueryClause
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSQueryClause` implement clauses used to configure `NSFetchRequest`s.
- SeeAlso: `QueryClause`
*/
@objc @objc
public protocol CSQueryClause { public protocol CSQueryClause {
@@ -59,11 +51,7 @@ public protocol CSQueryClause {
// MARK: - CSDeleteClause // MARK: - CSDeleteClause
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSDeleteClause` implement clauses used to configure `NSFetchRequest`s.
- SeeAlso: `DeleteClause`
*/
@objc @objc
public protocol CSDeleteClause { public protocol CSDeleteClause {
+3 -22
View File
@@ -28,33 +28,14 @@ import Foundation
// MARK: - CSCoreStore // MARK: - CSCoreStore
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSCoreStore` serves as the Objective-C bridging type for `CoreStore`.
- SeeAlso: `CoreStore`
*/
@available(*, deprecated, message: "Call methods directly from the CSDataStack instead")
@objc @objc
public final class CSCoreStore: NSObject { public final class CSCoreStore: NSObject {
/**
The default `CSDataStack` instance to be used. If `defaultStack` is not set before the first time accessed, a default-configured `CSDataStack` will be created.
- SeeAlso: `CSDataStack`
- Note: Changing the `defaultStack` is thread safe, but it is recommended to setup `CSDataStacks` on a common queue (e.g. the main queue).
*/
@objc @objc
public static var defaultStack: CSDataStack { public static var defaultStack: CSDataStack {
get { return CoreStoreDefaults.dataStack.bridgeToObjectiveC } get { fatalError() }
set { CoreStoreDefaults.dataStack = newValue.bridgeToSwift } set { fatalError() }
}
// MARK: Private
private override init() {
fatalError()
} }
} }
+5 -74
View File
@@ -29,99 +29,30 @@ import CoreData
// MARK: - CSDataStack // MARK: - CSDataStack
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.") @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
extension CSDataStack { extension CSDataStack {
/**
Asynchronously adds a `CSInMemoryStore` to the stack. Migrations are also initiated by default.
```
NSError *error;
NSProgress *migrationProgress = [dataStack
addInMemoryStorage:[CSInMemoryStore new]
completion:^(CSSetupResult *result) {
if (result.isSuccess) {
// ...
}
}
error: &error];
```
- parameter storage: the `CSInMemoryStore` instance
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `CSSetupResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a failure `CSSetupResult` result if an error occurs asynchronously.
*/
@objc @objc
public func addInMemoryStorage(_ storage: CSInMemoryStore, completion: @escaping (CSSetupResult) -> Void) { public func addInMemoryStorage(_ storage: CSInMemoryStore, completion: @escaping (CSSetupResult) -> Void) {
self.bridgeToSwift.addStorage( fatalError()
storage.bridgeToSwift,
completion: { completion($0.bridgeToObjectiveC) }
)
} }
/**
Asynchronously adds a `CSSQLiteStore` to the stack. Migrations are also initiated by default.
```
NSError *error;
NSProgress *migrationProgress = [dataStack
addInMemoryStorage:[[CSSQLiteStore alloc]
initWithFileName:@"core_data.sqlite"
configuration:@"Config1"]
completion:^(CSSetupResult *result) {
if (result.isSuccess) {
// ...
}
}
error: &error];
```
- parameter storage: the `CSSQLiteStore` instance
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `CSSetupResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a failure `CSSetupResult` result if an error occurs asynchronously. Note that the `CSLocalStorage` associated to the `-[CSSetupResult storage]` may not always be the same instance as the parameter argument if a previous `CSLocalStorage` was already added at the same URL and with the same configuration.
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
*/
@objc @objc
public func addSQLiteStorage(_ storage: CSSQLiteStore, completion: @escaping (CSSetupResult) -> Void, error: NSErrorPointer) -> Progress? { public func addSQLiteStorage(_ storage: CSSQLiteStore, completion: @escaping (CSSetupResult) -> Void, error: NSErrorPointer) -> Progress? {
return bridge(error) { fatalError()
self.bridgeToSwift.addStorage(
storage.bridgeToSwift,
completion: { completion($0.bridgeToObjectiveC) }
)
}
} }
/**
Migrates a `CSSQLiteStore` to match the `CSDataStack`'s managed object model version. This method does NOT add the migrated store to the data stack.
- parameter storage: the `CSSQLiteStore` instance
- parameter completion: the closure to be executed on the main queue when the migration completes, either due to success or failure. The closure's `CSMigrationResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a failure `CSSetupResult` result if an error occurs asynchronously.
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
*/
@objc @objc
public func upgradeStorageIfNeeded(_ storage: CSSQLiteStore, completion: @escaping (CSMigrationResult) -> Void, error: NSErrorPointer) -> Progress? { public func upgradeStorageIfNeeded(_ storage: CSSQLiteStore, completion: @escaping (CSMigrationResult) -> Void, error: NSErrorPointer) -> Progress? {
return bridge(error) { fatalError()
try self.bridgeToSwift.upgradeStorageIfNeeded(
storage.bridgeToSwift,
completion: { completion($0.bridgeToObjectiveC) }
)
}
} }
/**
Checks the migration steps required for the `CSSQLiteStore` to match the `CSDataStack`'s managed object model version.
- parameter storage: the `CSSQLiteStore` instance
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: a `CSMigrationType` array indicating the migration steps required for the store, or an empty array if the file does not exist yet. Otherwise, `nil` is returned and the `error` argument is set if either inspection of the store failed, or if no mapping model was found/inferred.
*/
@objc @objc
public func requiredMigrationsForSQLiteStore(_ storage: CSSQLiteStore, error: NSErrorPointer) -> [CSMigrationType]? { public func requiredMigrationsForSQLiteStore(_ storage: CSSQLiteStore, error: NSErrorPointer) -> [CSMigrationType]? {
return bridge(error) { fatalError()
try self.bridgeToSwift.requiredMigrationsForStorage(storage.bridgeToSwift)
}
} }
} }
+6 -114
View File
@@ -29,143 +29,35 @@ import CoreData
// MARK: - CSDataStack // MARK: - CSDataStack
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.") @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
extension CSDataStack { extension CSDataStack {
/**
Creates a `CSObjectMonitor` for the specified `NSManagedObject`. Multiple `ObjectObserver`s may then register themselves to be notified when changes are made to the `NSManagedObject`.
- parameter object: the `NSManagedObject` to observe changes from
- returns: an `ObjectMonitor` that monitors changes to `object`
*/
@objc @objc
public func monitorObject(_ object: NSManagedObject) -> CSObjectMonitor { public func monitorObject(_ object: NSManagedObject) -> CSObjectMonitor {
return self.bridgeToSwift.monitorObject(object).bridgeToObjectiveC fatalError()
} }
/**
Creates a `CSListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `CSListObserver`s may then register themselves to be notified when changes are made to the list.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- returns: a `CSListMonitor` instance that monitors changes to the list
*/
@objc @objc
public func monitorListFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor { public func monitorListFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor {
Internals.assert( fatalError()
Thread.isMainThread,
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
)
Internals.assert(
fetchClauses.contains { $0 is CSOrderBy },
"A CSListMonitor requires a CSOrderBy clause."
)
return ListMonitor(
dataStack: self.bridgeToSwift,
from: from.bridgeToSwift,
sectionBy: nil,
applyFetchClauses: { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
}
).bridgeToObjectiveC
} }
/**
Asynchronously creates a `CSListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `CSListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
- parameter createAsynchronously: the closure that receives the created `CSListMonitor` instance
- parameter from: a `CSFrom` clause indicating the entity type
- parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
*/
@objc @objc
public func monitorListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause]) { public func monitorListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause]) {
Internals.assert( fatalError()
Thread.isMainThread,
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
)
Internals.assert(
fetchClauses.contains { $0 is CSOrderBy },
"A CSListMonitor requires an CSOrderBy clause."
)
_ = ListMonitor(
dataStack: self.bridgeToSwift,
from: from.bridgeToSwift,
sectionBy: nil,
applyFetchClauses: { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
},
createAsynchronously: {
createAsynchronously($0.bridgeToObjectiveC)
}
)
} }
/**
Creates a `CSListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter sectionBy: a `CSSectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- returns: a `CSListMonitor` instance that monitors changes to the list
*/
@objc @objc
public func monitorSectionedListFrom(_ from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> CSListMonitor { public func monitorSectionedListFrom(_ from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> CSListMonitor {
Internals.assert( fatalError()
Thread.isMainThread,
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
)
Internals.assert(
fetchClauses.contains { $0 is CSOrderBy },
"A CSListMonitor requires an CSOrderBy clause."
)
return ListMonitor(
dataStack: self.bridgeToSwift,
from: from.bridgeToSwift,
sectionBy: sectionBy.bridgeToSwift,
applyFetchClauses: { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
}
).bridgeToObjectiveC
} }
/**
Asynchronously creates a `CSListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `CSListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
- parameter createAsynchronously: the closure that receives the created `CSListMonitor` instance
- parameter from: a `CSFrom` clause indicating the entity type
- parameter sectionBy: a `CSSectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
*/
public func monitorSectionedListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) { public func monitorSectionedListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) {
Internals.assert( fatalError()
Thread.isMainThread,
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
)
Internals.assert(
fetchClauses.contains { $0 is CSOrderBy },
"A CSListMonitor requires an CSOrderBy clause."
)
_ = ListMonitor(
dataStack: self.bridgeToSwift,
from: from.bridgeToSwift,
sectionBy: sectionBy.bridgeToSwift,
applyFetchClauses: { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
},
createAsynchronously: {
createAsynchronously($0.bridgeToObjectiveC)
}
)
} }
} }
+12 -126
View File
@@ -29,186 +29,72 @@ import CoreData
// MARK: - CSDataStack // MARK: - CSDataStack
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.") @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
extension CSDataStack { extension CSDataStack {
/**
Fetches the `NSManagedObject` instance in the transaction's context from a reference created from a transaction or from a different managed object context.
- parameter object: a reference to the object created/fetched outside the transaction
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/
@objc @objc
public func fetchExistingObject(_ object: NSManagedObject) -> Any? { public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
return self.bridgeToSwift.mainContext.fetchExisting(object) as NSManagedObject? fatalError()
} }
/**
Fetches the `NSManagedObject` instance in the transaction's context from an `NSManagedObjectID`.
- parameter objectID: the `NSManagedObjectID` for the object
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/
@objc @objc
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? { public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
return self.bridgeToSwift.mainContext.fetchExisting(objectID) as NSManagedObject? fatalError()
} }
/**
Fetches the `NSManagedObject` instances in the transaction's context from references created from a transaction or from a different managed object context.
- parameter objects: an array of `NSManagedObject`s created/fetched outside the transaction
- returns: the `NSManagedObject` array for objects that exists in the transaction
*/
@objc @objc
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] { public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
return self.bridgeToSwift.mainContext.fetchExisting(objects) as [NSManagedObject] fatalError()
} }
/**
Fetches the `NSManagedObject` instances in the transaction's context from a list of `NSManagedObjectID`.
- parameter objectIDs: the `NSManagedObjectID` array for the objects
- returns: the `NSManagedObject` array for objects that exists in the transaction
*/
@objc @objc
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] { public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
return self.bridgeToSwift.mainContext.fetchExisting(objectIDs) as [NSManagedObject] fatalError()
} }
/**
Fetches the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `CSFetchClause` instances for the fetch request. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s
*/
@objc @objc
public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? { public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
Internals.assert( fatalError()
Thread.isMainThread,
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.fetchOne(from, fetchClauses))?
.flatMap({ $0 })
} }
/**
Fetches all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter fetchClauses: a series of `CSFetchClause` instances for the fetch request. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s
*/
@objc @objc
public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? { public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
Internals.assert( fatalError()
Thread.isMainThread,
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.fetchAll(from, fetchClauses))
.flatMap({ $0 })
} }
/**
Fetches the number of `NSManagedObject`s that satisfy the specified `CSFetchClause`s. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter fetchClauses: a series of `CSFetchClause` instances for the fetch request. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- returns: the number `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/
@objc @objc
public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? { public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
Internals.assert( fatalError()
Thread.isMainThread,
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.fetchCount(from, fetchClauses))
.flatMap({ NSNumber(value: $0) })
} }
/**
Fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter fetchClauses: a series of `CSFetchClause` instances for the fetch request. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s
*/
@objc @objc
public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? { public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
Internals.assert( fatalError()
Thread.isMainThread,
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.fetchObjectID(from, fetchClauses))?
.flatMap({ $0 })
} }
/**
Fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `CSFetchClause`s. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/
@objc @objc
public func fetchObjectIDsFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? { public func fetchObjectIDsFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
Internals.assert( fatalError()
Thread.isMainThread,
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.fetchObjectIDs(from, fetchClauses))
.flatMap({ $0 })
} }
/**
Queries aggregate values as specified by the `CSQueryClause`s. Requires at least a `CSSelect` clause, and optional `CSWhere`, `CSOrderBy`, `CSGroupBy`, and `CSTweak` clauses.
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter selectClause: a `CSSelect` clause indicating the properties to fetch, and with the generic type indicating the return type.
- parameter queryClauses: a series of `CSQueryClause` instances for the query request. Accepts `CSWhere`, `CSOrderBy`, `CSGroupBy`, and `CSTweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/
@objc @objc
public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? { public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
Internals.assert( fatalError()
Thread.isMainThread,
"Attempted to query from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.queryValue(from, selectClause, queryClauses))
.flatMap({ $0 })
} }
/**
Queries a dictionary of attribute values as specified by the `CSQueryClause`s. Requires at least a `CSSelect` clause, and optional `CSWhere`, `CSOrderBy`, `CSGroupBy`, and `CSTweak` clauses.
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
- parameter from: a `CSFrom` clause indicating the entity type
- parameter selectClause: a `CSSelect` clause indicating the properties to fetch, and with the generic type indicating the return type.
- parameter queryClauses: a series of `CSQueryClause` instances for the query request. Accepts `CSWhere`, `CSOrderBy`, `CSGroupBy`, and `CSTweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/
@objc @objc
public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? { public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
Internals.assert( fatalError()
Thread.isMainThread,
"Attempted to query from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.queryAttributes(from, selectClause, queryClauses))
.flatMap({ $0 })
} }
} }
+6 -78
View File
@@ -28,108 +28,36 @@ import Foundation
// MARK: - CSDataStack // MARK: - CSDataStack
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.") @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
extension CSDataStack { extension CSDataStack {
/**
Begins a transaction asynchronously where `NSManagedObject` creates, updates, and deletes can be made.
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
*/
@objc @objc
public func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) { public func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
self.bridgeToSwift.perform( fatalError()
asynchronous: { (transaction) in
let csTransaction = transaction.bridgeToObjectiveC
closure(csTransaction)
if !transaction.isCommitted && transaction.hasChanges {
Internals.log(
.warning,
message: "The closure for the \(Internals.typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
)
}
try transaction.cancel()
},
completion: { _ in }
)
} }
/**
Begins a transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made.
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- parameter error: the `CSError` pointer that indicates the reason in case of an failure
- returns: `YES` if the commit succeeded, `NO` if the commit failed. If `NO`, the `error` argument will hold error information.
*/
@objc @objc
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void, error: NSErrorPointer) -> Bool { public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void, error: NSErrorPointer) -> Bool {
return bridge(error) { fatalError()
do {
try self.bridgeToSwift.perform(
synchronous: { (transaction) in
let csTransaction = transaction.bridgeToObjectiveC
closure(csTransaction)
if !transaction.isCommitted && transaction.hasChanges {
Internals.log(
.warning,
message: "The closure for the \(Internals.typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
)
}
try transaction.cancel()
}
)
}
catch CoreStoreError.userCancelled {
return
}
}
} }
/**
Begins a child transaction where `NSManagedObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms.
To support "undo" methods such as `-undo`, `-redo`, and `-rollback`, use the `-beginSafeWithSupportsUndo:` method passing `YES` to the argument. Without "undo" support, calling those methods will raise an exception.
- returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
@objc @objc
public func beginUnsafe() -> CSUnsafeDataTransaction { public func beginUnsafe() -> CSUnsafeDataTransaction {
return bridge { fatalError()
self.bridgeToSwift.beginUnsafe()
}
} }
/**
Begins a child transaction where `NSManagedObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms.
- prameter supportsUndo: `-undo`, `-redo`, and `-rollback` methods are only available when this parameter is `YES`, otherwise those method will raise an exception. Note that turning on Undo support may heavily impact performance especially on iOS or watchOS where memory is limited.
- returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
@objc @objc
public func beginUnsafeWithSupportsUndo(_ supportsUndo: Bool) -> CSUnsafeDataTransaction { public func beginUnsafeWithSupportsUndo(_ supportsUndo: Bool) -> CSUnsafeDataTransaction {
return bridge { fatalError()
self.bridgeToSwift.beginUnsafe(supportsUndo: supportsUndo)
}
} }
/**
Refreshes all registered objects `NSManagedObject`s in the `DataStack`.
*/
@objc @objc
public func refreshAndMergeAllObjects() { public func refreshAndMergeAllObjects() {
self.bridgeToSwift.refreshAndMergeAllObjects() fatalError()
} }
} }
+16 -103
View File
@@ -29,148 +29,66 @@ import CoreData
// MARK: - CSDataStack // MARK: - CSDataStack
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSDataStack` serves as the Objective-C bridging type for `DataStack`.
- SeeAlso: `DataStack`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc @objc
public final class CSDataStack: NSObject, CoreStoreObjectiveCType { public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
/**
Initializes a `CSDataStack` with default settings. CoreStore searches for <CFBundleName>.xcdatamodeld from the main `NSBundle` and loads an `NSManagedObjectModel` from it. An assertion is raised if the model could not be found.
*/
@objc @objc
public convenience override init() { public convenience override init() {
self.init(DataStack()) fatalError()
} }
/**
Initializes a `CSDataStack` from the model with the specified `modelName` in the specified `bundle`.
- 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 .xcdatamodeld 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 @objc
public convenience init(xcodeModelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) { public convenience init(xcodeModelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
self.init( fatalError()
DataStack(
xcodeModelName: xcodeModelName ?? DataStack.applicationName,
bundle: bundle ?? Bundle.main,
migrationChain: versionChain.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.
*/
@objc @objc
public var modelVersion: String { public var modelVersion: String {
return self.bridgeToSwift.modelVersion fatalError()
} }
/**
Returns the entity name-to-class type mapping from the `CSDataStack`'s model.
*/
@objc @objc
public func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] { public func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
return self.bridgeToSwift.entityTypesByName(for: type) fatalError()
} }
/**
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from stack's model.
*/
@objc @objc
public func entityDescriptionForClass(_ type: NSManagedObject.Type) -> NSEntityDescription? { public func entityDescriptionForClass(_ type: NSManagedObject.Type) -> NSEntityDescription? {
return self.bridgeToSwift.entityDescription(for: type) fatalError()
} }
/**
Creates an `CSInMemoryStore` with default parameters and adds it to the stack. This method blocks until completion.
```
CSSQLiteStore *storage = [dataStack addInMemoryStorageAndWaitAndReturnError:&error];
```
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSInMemoryStore` added to the stack
*/
@objc @objc
@discardableResult @discardableResult
public func addInMemoryStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSInMemoryStore? { public func addInMemoryStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSInMemoryStore? {
return bridge(error) { fatalError()
try self.bridgeToSwift.addStorageAndWait(InMemoryStore())
}
} }
/**
Creates an `CSSQLiteStore` with default parameters and adds it to the stack. This method blocks until completion.
```
CSSQLiteStore *storage = [dataStack addSQLiteStorageAndWaitAndReturnError:&error];
```
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSSQLiteStore` added to the stack
*/
@objc @objc
@discardableResult @discardableResult
public func addSQLiteStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSSQLiteStore? { public func addSQLiteStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSSQLiteStore? {
return bridge(error) { fatalError()
try self.bridgeToSwift.addStorageAndWait(SQLiteStore())
}
} }
/**
Adds a `CSInMemoryStore` to the stack and blocks until completion.
```
NSError *error;
CSInMemoryStore *storage = [dataStack
addStorageAndWait: [[CSInMemoryStore alloc] initWithConfiguration: @"Config1"]
error: &error];
```
- parameter storage: the `CSInMemoryStore`
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSInMemoryStore` added to the stack
*/
@objc @objc
@discardableResult @discardableResult
public func addInMemoryStorageAndWait(_ storage: CSInMemoryStore, error: NSErrorPointer) -> CSInMemoryStore? { public func addInMemoryStorageAndWait(_ storage: CSInMemoryStore, error: NSErrorPointer) -> CSInMemoryStore? {
return bridge(error) { fatalError()
try self.bridgeToSwift.addStorageAndWait(storage.bridgeToSwift)
}
} }
/**
Adds a `CSSQLiteStore` to the stack and blocks until completion.
```
NSError *error;
CSSQLiteStore *storage = [dataStack
addStorageAndWait: [[CSSQLiteStore alloc] initWithConfiguration: @"Config1"]
error: &error];
```
- parameter storage: the `CSSQLiteStore`
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSSQLiteStore` added to the stack
*/
@objc @objc
@discardableResult @discardableResult
public func addSQLiteStorageAndWait(_ storage: CSSQLiteStore, error: NSErrorPointer) -> CSSQLiteStore? { public func addSQLiteStorageAndWait(_ storage: CSSQLiteStore, error: NSErrorPointer) -> CSSQLiteStore? {
return bridge(error) { fatalError()
try self.bridgeToSwift.addStorageAndWait(storage.bridgeToSwift)
}
} }
@@ -178,21 +96,17 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
public override var hash: Int { public override var hash: Int {
return ObjectIdentifier(self.bridgeToSwift).hashValue fatalError()
} }
public override func isEqual(_ object: Any?) -> Bool { public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSDataStack else { fatalError()
return false
}
return self.bridgeToSwift == object.bridgeToSwift
} }
public override var description: String { public override var description: String {
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)" fatalError()
} }
@@ -202,21 +116,20 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
public init(_ swiftValue: DataStack) { public init(_ swiftValue: DataStack) {
self.bridgeToSwift = swiftValue fatalError()
super.init()
} }
} }
// MARK: - DataStack // MARK: - DataStack
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.") @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
extension DataStack: CoreStoreSwiftType { extension DataStack: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
public var bridgeToObjectiveC: CSDataStack { public var bridgeToObjectiveC: CSDataStack {
return CSDataStack(self) fatalError()
} }
} }
+1 -11
View File
@@ -29,23 +29,13 @@ import Foundation
// MARK: - CSDynamicSchema // MARK: - CSDynamicSchema
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSDynamicSchema` serves as the Objective-C bridging type for `DynamicSchema`.
- SeeAlso: `DynamicSchema`
*/
@objc @objc
public protocol CSDynamicSchema { public protocol CSDynamicSchema {
/**
The version string for this model schema.
*/
@objc @objc
var modelVersion: ModelVersion { get } var modelVersion: ModelVersion { get }
/**
Do not call this directly. The `NSManagedObjectModel` for this schema may be created lazily and using this method directly may affect the integrity of the model.
*/
@objc @objc
func rawModel() -> NSManagedObjectModel func rawModel() -> NSManagedObjectModel
} }
+11 -217
View File
@@ -29,31 +29,18 @@ import CoreData
// MARK: - CSError // MARK: - CSError
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
All errors thrown from CoreStore are expressed in `CSError`s.
- SeeAlso: `CoreStoreError`
*/
@objc @objc
public final class CSError: NSError { public final class CSError: NSError {
/** // MARK: Public
The `NSError` error domain for `CSError`.
- SeeAlso: `CoreStoreErrorErrorDomain`
*/
@objc @objc
public static let errorDomain = CoreStoreErrorDomain public static let errorDomain = CoreStoreErrorDomain
public var bridgeToSwift: CoreStoreError { public var bridgeToSwift: CoreStoreError {
if let swift = self.swiftError { fatalError()
return swift
}
let swift = CoreStoreError(_bridgedNSError: self) ?? .unknown
self.swiftError = swift
return swift
} }
@@ -61,249 +48,56 @@ public final class CSError: NSError {
public override var hash: Int { public override var hash: Int {
return self.bridgeToSwift.hashValue fatalError()
} }
public override func isEqual(_ object: Any?) -> Bool { public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSError else { fatalError()
return false
}
return self.bridgeToSwift == object.bridgeToSwift
} }
public override var description: String { public override var description: String {
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)" fatalError()
} }
/**
Do not call directly!
*/
public init(_ swiftValue: CoreStoreError) { public init(_ swiftValue: CoreStoreError) {
self.swiftError = swiftValue fatalError()
super.init(domain: CoreStoreError.errorDomain, code: swiftValue.errorCode, userInfo: swiftValue.errorUserInfo)
} }
public required init?(coder aDecoder: NSCoder) { public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) fatalError()
} }
// MARK: Private
private var swiftError: CoreStoreError?
} }
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension CSError: CoreStoreObjectiveCType {}
// MARK: - CSErrorCode // MARK: - CSErrorCode
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `NSError` error codes for `CSError.Domain`.
- SeeAlso: `CSError`
- SeeAlso: `CoreStoreError`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc @objc
public enum CSErrorCode: Int { public enum CSErrorCode: Int {
/**
A failure occured because of an unknown error.
*/
case unknownError case unknownError
/**
The `NSPersistentStore` could note be initialized because another store existed at the specified `NSURL`.
*/
case differentStorageExistsAtURL case differentStorageExistsAtURL
/**
An `NSMappingModel` could not be found for a specific source and destination model versions.
*/
case mappingModelNotFound case mappingModelNotFound
/**
Progressive migrations are disabled for a store, but an `NSMappingModel` could not be found for a specific source and destination model versions.
*/
case progressiveMigrationRequired case progressiveMigrationRequired
/**
An internal SDK call failed with the specified "NSError" userInfo key.
*/
case internalError case internalError
/**
The transaction was terminated by a user-thrown error with the specified "Error" userInfo key.
*/
case userError case userError
/**
The transaction was cancelled by the user.
*/
case userCancelled case userCancelled
} }
// MARK: - CoreStoreError // MARK: - CoreStoreError
extension CoreStoreError: _ObjectiveCBridgeableError { @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
// MARK: _ObjectiveCBridgeableError
public init?(_bridgedNSError error: NSError) {
guard error.domain == CoreStoreErrorDomain else {
if error is CSError {
self = .internalError(NSError: error)
return
}
return nil
}
guard let code = CoreStoreErrorCode(rawValue: error.code) else {
if error is CSError {
self = .unknown
return
}
return nil
}
let info = error.userInfo
switch code {
case .unknownError:
self = .unknown
case .differentStorageExistsAtURL:
guard case let existingPersistentStoreURL as URL = info["existingPersistentStoreURL"] else {
self = .unknown
return
}
self = .differentStorageExistsAtURL(existingPersistentStoreURL: existingPersistentStoreURL)
case .mappingModelNotFound:
guard let localStoreURL = info["localStoreURL"] as? URL,
let targetModel = info["targetModel"] as? NSManagedObjectModel,
let targetModelVersion = info["targetModelVersion"] as? String else {
self = .unknown
return
}
self = .mappingModelNotFound(localStoreURL: localStoreURL, targetModel: targetModel, targetModelVersion: targetModelVersion)
case .progressiveMigrationRequired:
guard let localStoreURL = info["localStoreURL"] as? URL else {
self = .unknown
return
}
self = .progressiveMigrationRequired(localStoreURL: localStoreURL)
case .asynchronousMigrationRequired:
guard
let localStoreURL = info["localStoreURL"] as? URL,
case let nsError as NSError = info["NSError"]
else {
self = .unknown
return
}
self = .asynchronousMigrationRequired(localStoreURL: localStoreURL, NSError: nsError)
case .internalError:
guard case let nsError as NSError = info["NSError"] else {
self = .unknown
return
}
self = .internalError(NSError: nsError)
case .userError:
guard case let error as Error = info["Error"] else {
self = .unknown
return
}
self = .userError(error: error)
case .userCancelled:
self = .userCancelled
case .persistentStoreNotFound:
guard let entity = info["entity"] as? DynamicObject.Type else {
self = .unknown
return
}
self = .persistentStoreNotFound(entity: entity)
}
}
}
// MARK: - Error
extension Error {
// MARK: Internal
internal var bridgeToSwift: CoreStoreError {
switch self {
case let error as CoreStoreError:
return error
case let error as CSError:
return error.bridgeToSwift
case let error as NSError where Self.self is NSError.Type:
return .internalError(NSError: error)
default:
return .unknown
}
}
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
internal var bridgeToObjectiveC: NSError {
switch self {
case let error as CoreStoreError:
return error.bridgeToObjectiveC
case let error as CSError:
return error
default:
return self as NSError
}
}
}
// MARK: - CoreStoreError
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension CoreStoreError: CoreStoreSwiftType { extension CoreStoreError: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
public var bridgeToObjectiveC: CSError { public var bridgeToObjectiveC: CSError {
return CSError(self) fatalError()
} }
} }
+10 -91
View File
@@ -29,107 +29,38 @@ import CoreData
// MARK: - CSFrom // MARK: - CSFrom
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSFrom` serves as the Objective-C bridging type for `From`.
- SeeAlso: `From`
*/
@objc @objc
public final class CSFrom: NSObject { public final class CSFrom: NSObject {
/**
The associated `NSManagedObject` entity class
*/
@objc @objc
public var entityClass: AnyClass { public var entityClass: AnyClass {
return self.bridgeToSwift.entityClass fatalError()
} }
/**
The `NSPersistentStore` configuration names to associate objects from.
May contain `NSString` instances to pertain to named configurations, or `NSNull` to pertain to the default configuration
*/
@objc @objc
public var configurations: [Any]? { public var configurations: [Any]? {
return self.bridgeToSwift.configurations?.map { fatalError()
switch $0 {
case nil: return NSNull()
case let string as NSString: return string
}
}
} }
/**
Initializes a `CSFrom` clause with the specified entity class.
```
MyPersonEntity *people = [transaction fetchAllFrom:CSFromClass([MyPersonEntity class])];
```
- parameter entityClass: the `NSManagedObject` class type to be created
*/
@objc @objc
public convenience init(entityClass: NSManagedObject.Type) { public convenience init(entityClass: NSManagedObject.Type) {
self.init(From(entityClass)) fatalError()
} }
/**
Initializes a `CSFrom` clause with the specified configurations.
```
MyPersonEntity *people = [transaction fetchAllFrom:
CSFromClass([MyPersonEntity class], @"Config1")];
```
- parameter entityClass: the associated `NSManagedObject` entity class
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
*/
@objc @objc
public convenience init(entityClass: NSManagedObject.Type, configuration: Any) { public convenience init(entityClass: NSManagedObject.Type, configuration: Any) {
switch configuration { fatalError()
case let string as String:
self.init(From(entityClass, string))
case is NSNull:
self.init(From(entityClass, nil))
default:
Internals.abort("The configuration argument only accepts NSString and NSNull values")
}
} }
/**
Initializes a `CSFrom` clause with the specified configurations.
```
MyPersonEntity *people = [transaction fetchAllFrom:
CSFromClass([MyPersonEntity class],
@[[NSNull null], @"Config1"])];
```
- parameter entityClass: the associated `NSManagedObject` entity class
- parameter configurations: an array of the `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
*/
@objc @objc
public convenience init(entityClass: NSManagedObject.Type, configurations: [Any]) { public convenience init(entityClass: NSManagedObject.Type, configurations: [Any]) {
var arguments = [ModelConfiguration]() fatalError()
for configuration in configurations {
switch configuration {
case let string as String:
arguments.append(string)
case is NSNull:
arguments.append(nil)
default:
Internals.abort("The configurations argument only accepts NSString and NSNull values")
}
}
self.init(From(entityClass, arguments))
} }
@@ -137,7 +68,7 @@ public final class CSFrom: NSObject {
public override var description: String { public override var description: String {
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)" fatalError()
} }
@@ -147,32 +78,20 @@ public final class CSFrom: NSObject {
public init<O: NSManagedObject>(_ swiftValue: From<O>) { public init<O: NSManagedObject>(_ swiftValue: From<O>) {
self.bridgeToSwift = swiftValue.downcast() fatalError()
super.init()
} }
} }
// MARK: - From // MARK: - From
@available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
extension From where O: NSManagedObject { extension From where O: NSManagedObject {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
public var bridgeToObjectiveC: CSFrom { public var bridgeToObjectiveC: CSFrom {
return CSFrom(self) fatalError()
}
// MARK: FilePrivate
fileprivate func downcast() -> From<NSManagedObject> {
return From<NSManagedObject>(
entityClass: self.entityClass,
configurations: self.configurations,
findPersistentStores: self.findPersistentStores
)
} }
} }
+11 -40
View File
@@ -29,43 +29,26 @@ import CoreData
// MARK: - CSGroupBy // MARK: - CSGroupBy
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSGroupBy` serves as the Objective-C bridging type for `GroupBy`.
- SeeAlso: `GroupBy`
*/
@objc @objc
public final class CSGroupBy: NSObject, CSQueryClause { public final class CSGroupBy: NSObject, CSQueryClause {
/**
The list of key path strings to group results with
*/
@objc @objc
public var keyPaths: [KeyPathString] { public var keyPaths: [KeyPathString] {
return self.bridgeToSwift.keyPaths fatalError()
} }
/**
Initializes a `CSGroupBy` clause with a key path string
- parameter keyPath: a key path string to group results with
*/
@objc @objc
public convenience init(keyPath: KeyPathString) { public convenience init(keyPath: KeyPathString) {
self.init(GroupBy(keyPath)) fatalError()
} }
/**
Initializes a `CSGroupBy` clause with a list of key path strings
- parameter keyPaths: a list of key path strings to group results with
*/
@objc @objc
public convenience init(keyPaths: [KeyPathString]) { public convenience init(keyPaths: [KeyPathString]) {
self.init(GroupBy(keyPaths)) fatalError()
} }
@@ -73,21 +56,17 @@ public final class CSGroupBy: NSObject, CSQueryClause {
public override var hash: Int { public override var hash: Int {
return self.bridgeToSwift.hashValue fatalError()
} }
public override func isEqual(_ object: Any?) -> Bool { public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSGroupBy else { fatalError()
return false
}
return self.bridgeToSwift == object.bridgeToSwift
} }
public override var description: String { public override var description: String {
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)" fatalError()
} }
@@ -96,7 +75,7 @@ public final class CSGroupBy: NSObject, CSQueryClause {
@objc @objc
public func applyToFetchRequest(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) { public func applyToFetchRequest(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) {
self.bridgeToSwift.applyToFetchRequest(fetchRequest) fatalError()
} }
@@ -106,28 +85,20 @@ public final class CSGroupBy: NSObject, CSQueryClause {
public init<O: NSManagedObject>(_ swiftValue: GroupBy<O>) { public init<O: NSManagedObject>(_ swiftValue: GroupBy<O>) {
self.bridgeToSwift = swiftValue.downcast() fatalError()
super.init()
} }
} }
// MARK: - GroupBy // MARK: - GroupBy
@available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
extension GroupBy where O: NSManagedObject { extension GroupBy where O: NSManagedObject {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
public var bridgeToObjectiveC: CSGroupBy { public var bridgeToObjectiveC: CSGroupBy {
return CSGroupBy(self) fatalError()
}
// MARK: FilePrivate
fileprivate func downcast() -> GroupBy<NSManagedObject> {
return GroupBy<NSManagedObject>(self.keyPaths)
} }
} }
+11 -38
View File
@@ -29,60 +29,38 @@ import CoreData
// MARK: - CSInMemoryStore // MARK: - CSInMemoryStore
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSInMemoryStore` serves as the Objective-C bridging type for `InMemoryStore`.
- SeeAlso: `InMemoryStore`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc @objc
public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjectiveCType { public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjectiveCType {
/**
Initializes a `CSInMemoryStore` for the specified configuration
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration.
*/
@objc @objc
public convenience init(configuration: ModelConfiguration) { public convenience init(configuration: ModelConfiguration) {
self.init(InMemoryStore(configuration: configuration)) fatalError()
} }
/**
Initializes a `CSInMemoryStore` with the "Default" configuration
*/
@objc @objc
public convenience override init() { public convenience override init() {
self.init(InMemoryStore()) fatalError()
} }
// MARK: StorageInterface // MARK: StorageInterface
/**
The string identifier for the `NSPersistentStore`'s `type` property. For `CSInMemoryStore`s, this is always set to `NSInMemoryStoreType`.
*/
@objc @objc
public static let storeType = NSInMemoryStoreType public static let storeType = NSInMemoryStoreType
/**
The configuration name in the model file
*/
@objc @objc
public var configuration: ModelConfiguration { public var configuration: ModelConfiguration {
return self.bridgeToSwift.configuration fatalError()
} }
/**
The options dictionary for the `NSPersistentStore`. For `CSInMemoryStore`s, this is always set to `nil`.
*/
@objc @objc
public var storeOptions: [AnyHashable: Any]? { public var storeOptions: [AnyHashable: Any]? {
return self.bridgeToSwift.storeOptions fatalError()
} }
@@ -90,21 +68,17 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
public override var hash: Int { public override var hash: Int {
return ObjectIdentifier(self.bridgeToSwift).hashValue fatalError()
} }
public override func isEqual(_ object: Any?) -> Bool { public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSInMemoryStore else { fatalError()
return false
}
return self.bridgeToSwift === object.bridgeToSwift
} }
public override var description: String { public override var description: String {
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)" fatalError()
} }
@@ -114,21 +88,20 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
public required init(_ swiftValue: InMemoryStore) { public required init(_ swiftValue: InMemoryStore) {
self.bridgeToSwift = swiftValue fatalError()
super.init()
} }
} }
// MARK: - InMemoryStore // MARK: - InMemoryStore
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.") @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
extension InMemoryStore: CoreStoreSwiftType { extension InMemoryStore: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
public var bridgeToObjectiveC: CSInMemoryStore { public var bridgeToObjectiveC: CSInMemoryStore {
return CSInMemoryStore(self) fatalError()
} }
} }
+11 -55
View File
@@ -29,60 +29,32 @@ import CoreData
// MARK: - CSInto // MARK: - CSInto
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSInto` serves as the Objective-C bridging type for `Into<T>`.
- SeeAlso: `Into`
*/
@objc @objc
public final class CSInto: NSObject { public final class CSInto: NSObject {
/**
The associated `NSManagedObject` entity class
*/
@objc @objc
public var entityClass: NSManagedObject.Type { public var entityClass: NSManagedObject.Type {
return self.bridgeToSwift.entityClass fatalError()
} }
/**
The `NSPersistentStore` configuration name to associate objects from.
May contain a `String` to pertain to a named configuration, or `nil` to pertain to the default configuration
*/
@objc @objc
public var configuration: ModelConfiguration { public var configuration: ModelConfiguration {
return self.bridgeToSwift.configuration fatalError()
} }
/**
Initializes a `CSInto` clause with the specified entity class.
```
MyPersonEntity *person = [transaction createInto:
CSIntoClass([MyPersonEntity class])];
```
- parameter entityClass: the `NSManagedObject` class type to be created
*/
@objc @objc
public convenience init(entityClass: NSManagedObject.Type) { public convenience init(entityClass: NSManagedObject.Type) {
self.init(Into(entityClass)) fatalError()
} }
/**
Initializes a `CSInto` clause with the specified configuration.
```
MyPersonEntity *person = [transaction createInto:
CSIntoClass([MyPersonEntity class])];
```
- parameter entityClass: the `NSManagedObject` class type to be created
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
*/
@objc @objc
public convenience init(entityClass: NSManagedObject.Type, configuration: ModelConfiguration) { public convenience init(entityClass: NSManagedObject.Type, configuration: ModelConfiguration) {
self.init(Into(entityClass, configuration)) fatalError()
} }
@@ -90,21 +62,17 @@ public final class CSInto: NSObject {
public override var hash: Int { public override var hash: Int {
return self.bridgeToSwift.hashValue fatalError()
} }
public override func isEqual(_ object: Any?) -> Bool { public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSInto else { fatalError()
return false
}
return self.bridgeToSwift == object.bridgeToSwift
} }
public override var description: String { public override var description: String {
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)" fatalError()
} }
@@ -114,8 +82,7 @@ public final class CSInto: NSObject {
public required init<O: NSManagedObject>(_ swiftValue: Into<O>) { public required init<O: NSManagedObject>(_ swiftValue: Into<O>) {
self.bridgeToSwift = swiftValue.downcast() fatalError()
super.init()
} }
} }
@@ -126,20 +93,9 @@ extension Into where O: NSManagedObject {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
@available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
public var bridgeToObjectiveC: CSInto { public var bridgeToObjectiveC: CSInto {
return CSInto(self) fatalError()
}
// MARK: FilePrivate
fileprivate func downcast() -> Into<NSManagedObject> {
return Into<NSManagedObject>(
entityClass: self.entityClass,
configuration: self.configuration,
inferStoreIfPossible: self.inferStoreIfPossible
)
} }
} }
+36 -350
View File
@@ -29,481 +29,183 @@ import CoreData
// MARK: - CSListMonitor // MARK: - CSListMonitor
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
The `CSListMonitor` serves as the Objective-C bridging type for `ListMonitor<T>`.
- SeeAlso: `ListMonitor`
*/
@objc @objc
public final class CSListMonitor: NSObject { public final class CSListMonitor: NSObject {
// MARK: Public (Accessors) // MARK: Public (Accessors)
/**
Returns the object at the given index within the first section. This subscript indexer is typically used for `CSListMonitor`s created without section groupings.
- parameter index: the index of the object. Using an index above the valid range will raise an exception.
- returns: the `NSManagedObject` at the specified index
*/
@objc @objc
public subscript(index: Int) -> Any { public subscript(index: Int) -> Any {
return self.bridgeToSwift[index] fatalError()
} }
/**
Returns the object at the given index, or `nil` if out of bounds. This indexer is typically used for `CSListMonitor`s created without section groupings.
- parameter index: the index for the object. Using an index above the valid range will return `nil`.
- returns: the `NSManagedObject` at the specified index, or `nil` if out of bounds
*/
@objc @objc
public func objectAtSafeIndex(_ index: Int) -> Any? { public func objectAtSafeIndex(_ index: Int) -> Any? {
return self.bridgeToSwift[safeIndex: index] fatalError()
} }
/**
Returns the object at the given `sectionIndex` and `itemIndex`. This indexer is typically used for `CSListMonitor`s created as sectioned lists.
- parameter sectionIndex: the section index for the object. Using a `sectionIndex` with an invalid range will raise an exception.
- parameter itemIndex: the index for the object within the section. Using an `itemIndex` with an invalid range will raise an exception.
- returns: the `NSManagedObject` at the specified section and item index
*/
@objc @objc
public func objectAtSectionIndex(_ sectionIndex: Int, itemIndex: Int) -> Any { public func objectAtSectionIndex(_ sectionIndex: Int, itemIndex: Int) -> Any {
return self.bridgeToSwift[sectionIndex, itemIndex] fatalError()
} /** }
Returns the object at the given section and item index, or `nil` if out of bounds. This indexer is typically used for `CSListMonitor`s created as sectioned lists.
- parameter sectionIndex: the section index for the object. Using a `sectionIndex` with an invalid range will return `nil`.
- parameter itemIndex: the index for the object within the section. Using an `itemIndex` with an invalid range will return `nil`.
- returns: the `NSManagedObject` at the specified section and item index, or `nil` if out of bounds
*/
@objc @objc
public func objectAtSafeSectionIndex(_ sectionIndex: Int, safeItemIndex itemIndex: Int) -> Any? { public func objectAtSafeSectionIndex(_ sectionIndex: Int, safeItemIndex itemIndex: Int) -> Any? {
return self.bridgeToSwift[safeSectionIndex: sectionIndex, safeItemIndex: itemIndex] fatalError()
} }
/**
Returns the object at the given `NSIndexPath`. This subscript indexer is typically used for `CSListMonitor`s created as sectioned lists.
- parameter indexPath: the `NSIndexPath` for the object. Using an `indexPath` with an invalid range will raise an exception.
- returns: the `NSManagedObject` at the specified index path
*/
@objc @objc
public func objectAtIndexPath(_ indexPath: IndexPath) -> Any { public func objectAtIndexPath(_ indexPath: IndexPath) -> Any {
return self.bridgeToSwift[indexPath] fatalError()
} }
/**
Returns the object at the given `NSIndexPath`, or `nil` if out of bounds. This subscript indexer is typically used for `CSListMonitor`s created as sectioned lists.
- parameter indexPath: the `NSIndexPath` for the object. Using an `indexPath` with an invalid range will return `nil`.
- returns: the `NSManagedObject` at the specified index path, or `nil` if out of bounds
*/
@objc @objc
public func objectAtSafeIndexPath(_ indexPath: IndexPath) -> Any? { public func objectAtSafeIndexPath(_ indexPath: IndexPath) -> Any? {
return self.bridgeToSwift[safeIndexPath: indexPath] fatalError()
} }
/**
Checks if the `CSListMonitor` has at least one object in any section.
- returns: `YES` if at least one object in any section exists, `NO` otherwise
*/
@objc @objc
public func hasObjects() -> Bool { public func hasObjects() -> Bool {
return self.bridgeToSwift.hasObjects() fatalError()
} }
/**
Checks if the `CSListMonitor` has at least one object the specified section.
- parameter section: the section index. Using an index outside the valid range will return `NO`.
- returns: `YES` if at least one object in the specified section exists, `NO` otherwise
*/
@objc @objc
public func hasObjectsInSection(_ section: Int) -> Bool { public func hasObjectsInSection(_ section: Int) -> Bool {
return self.bridgeToSwift.hasObjects(in: section) fatalError()
} }
/**
Returns all objects in all sections
- returns: all objects in all sections
*/
@objc @objc
public func objectsInAllSections() -> [NSManagedObject] { public func objectsInAllSections() -> [NSManagedObject] {
return self.bridgeToSwift.objectsInAllSections() fatalError()
} }
/**
Returns all objects in the specified section
- parameter section: the section index. Using an index outside the valid range will raise an exception.
- returns: all objects in the specified section
*/
@objc @objc
public func objectsInSection(_ section: Int) -> [NSManagedObject] { public func objectsInSection(_ section: Int) -> [NSManagedObject] {
return self.bridgeToSwift.objects(in: section) fatalError()
} }
/**
Returns all objects in the specified section, or `nil` if out of bounds.
- parameter section: the section index. Using an index outside the valid range will return `nil`.
- returns: all objects in the specified section, or `nil` if out of bounds
*/
@objc @objc
public func objectsInSafeSection(safeSectionIndex section: Int) -> [NSManagedObject]? { public func objectsInSafeSection(safeSectionIndex section: Int) -> [NSManagedObject]? {
return self.bridgeToSwift.objects(safelyIn: section) fatalError()
} }
/**
Returns the number of sections
- returns: the number of sections
*/
@objc @objc
public func numberOfSections() -> Int { public func numberOfSections() -> Int {
return self.bridgeToSwift.numberOfSections() fatalError()
} }
/**
Returns the number of objects in all sections
- returns: the number of objects in all sections
*/
@objc @objc
public func numberOfObjects() -> Int { public func numberOfObjects() -> Int {
return self.bridgeToSwift.numberOfObjects() fatalError()
} }
/**
Returns the number of objects in the specified section
- parameter section: the section index. Using an index outside the valid range will raise an exception.
- returns: the number of objects in the specified section
*/
@objc @objc
public func numberOfObjectsInSection(_ section: Int) -> Int { public func numberOfObjectsInSection(_ section: Int) -> Int {
return self.bridgeToSwift.numberOfObjects(in: section) fatalError()
} }
/**
Returns the number of objects in the specified section, or `nil` if out of bounds.
- parameter section: the section index. Using an index outside the valid range will return `nil`.
- returns: the number of objects in the specified section, or `nil` if out of bounds
*/
@objc @objc
public func numberOfObjectsInSafeSection(safeSectionIndex section: Int) -> NSNumber? { public func numberOfObjectsInSafeSection(safeSectionIndex section: Int) -> NSNumber? {
return self.bridgeToSwift fatalError()
.numberOfObjects(safelyIn: section)
.flatMap { NSNumber(value: $0) }
} }
/**
Returns the `NSFetchedResultsSectionInfo` for the specified section
- parameter section: the section index. Using an index outside the valid range will raise an exception.
- returns: the `NSFetchedResultsSectionInfo` for the specified section
*/
@objc @objc
public func sectionInfoAtIndex(_ section: Int) -> NSFetchedResultsSectionInfo { public func sectionInfoAtIndex(_ section: Int) -> NSFetchedResultsSectionInfo {
return self.bridgeToSwift.sectionInfo(at: section) fatalError()
} }
/**
Returns the `NSFetchedResultsSectionInfo` for the specified section, or `nil` if out of bounds.
- parameter section: the section index. Using an index outside the valid range will return `nil`.
- returns: the `NSFetchedResultsSectionInfo` for the specified section, or `nil` if the section index is out of bounds.
*/
@objc @objc
public func sectionInfoAtSafeSectionIndex(safeSectionIndex section: Int) -> NSFetchedResultsSectionInfo? { public func sectionInfoAtSafeSectionIndex(safeSectionIndex section: Int) -> NSFetchedResultsSectionInfo? {
return self.bridgeToSwift.sectionInfo(safelyAt: section) fatalError()
} }
/**
Returns the `NSFetchedResultsSectionInfo`s for all sections
- returns: the `NSFetchedResultsSectionInfo`s for all sections
*/
@objc @objc
public func sections() -> [NSFetchedResultsSectionInfo] { public func sections() -> [NSFetchedResultsSectionInfo] {
return self.bridgeToSwift.sections() fatalError()
} }
/**
Returns the target section for a specified "Section Index" title and index.
- parameter title: the title of the Section Index
- parameter index: the index of the Section Index
- returns: the target section for the specified "Section Index" title and index.
*/
@objc @objc
public func targetSectionForSectionIndexTitle(title: String, index: Int) -> Int { public func targetSectionForSectionIndexTitle(title: String, index: Int) -> Int {
return self.bridgeToSwift.targetSection(forSectionIndexTitle: title, at: index) fatalError()
} }
/**
Returns the section index titles for all sections
- returns: the section index titles for all sections
*/
@objc @objc
public func sectionIndexTitles() -> [String] { public func sectionIndexTitles() -> [String] {
return self.bridgeToSwift.sectionIndexTitles() fatalError()
} }
/**
Returns the index of the `NSManagedObject` if it exists in the `CSListMonitor`'s fetched objects, or `nil` if not found.
- parameter object: the `NSManagedObject` to search the index of
- returns: the index of the `NSManagedObject` if it exists in the `CSListMonitor`'s fetched objects, or `nil` if not found.
*/
@objc @objc
public func indexOf(_ object: NSManagedObject) -> NSNumber? { public func indexOf(_ object: NSManagedObject) -> NSNumber? {
return self.bridgeToSwift fatalError()
.index(of: object)
.flatMap { NSNumber(value: $0) }
} }
/**
Returns the `NSIndexPath` of the `NSManagedObject` if it exists in the `CSListMonitor`'s fetched objects, or `nil` if not found.
- parameter object: the `NSManagedObject` to search the index of
- returns: the `NSIndexPath` of the `NSManagedObject` if it exists in the `ListMonitor`'s fetched objects, or `nil` if not found.
*/
@objc @objc
public func indexPathOf(_ object: NSManagedObject) -> IndexPath? { public func indexPathOf(_ object: NSManagedObject) -> IndexPath? {
return self.bridgeToSwift.indexPath(of: object) fatalError()
} }
// MARK: Public (Observers) // MARK: Public (Observers)
/**
Registers a `CSListObserver` to be notified when changes to the receiver's list occur.
To prevent retain-cycles, `CSListMonitor` only keeps `weak` references to its observers.
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
Calling `-addListObserver:` multiple times on the same observer is safe, as `CSListMonitor` unregisters previous notifications to the observer before re-registering them.
- parameter observer: a `CSListObserver` to send change notifications to
*/
@objc @objc
public func addListObserver(_ observer: CSListObserver) { public func addListObserver(_ observer: CSListObserver) {
let swift = self.bridgeToSwift fatalError()
swift.unregisterObserver(observer)
swift.registerObserver(
observer,
willChange: { (observer, monitor) in
observer.listMonitorWillChange?(monitor.bridgeToObjectiveC)
},
didChange: { (observer, monitor) in
observer.listMonitorDidChange?(monitor.bridgeToObjectiveC)
},
willRefetch: { (observer, monitor) in
observer.listMonitorWillRefetch?(monitor.bridgeToObjectiveC)
},
didRefetch: { (observer, monitor) in
observer.listMonitorDidRefetch?(monitor.bridgeToObjectiveC)
}
)
} }
/**
Registers a `CSListObjectObserver` to be notified when changes to the receiver's list occur.
To prevent retain-cycles, `CSListMonitor` only keeps `weak` references to its observers.
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
Calling `-addListObjectObserver:` multiple times on the same observer is safe, as `ListMonitor` unregisters previous notifications to the observer before re-registering them.
- parameter observer: a `CSListObjectObserver` to send change notifications to
*/
public func addListObjectObserver(_ observer: CSListObjectObserver) { public func addListObjectObserver(_ observer: CSListObjectObserver) {
let swift = self.bridgeToSwift fatalError()
swift.unregisterObserver(observer)
swift.registerObserver(
observer,
willChange: { (observer, monitor) in
observer.listMonitorWillChange?(monitor.bridgeToObjectiveC)
},
didChange: { (observer, monitor) in
observer.listMonitorDidChange?(monitor.bridgeToObjectiveC)
},
willRefetch: { (observer, monitor) in
observer.listMonitorWillRefetch?(monitor.bridgeToObjectiveC)
},
didRefetch: { (observer, monitor) in
observer.listMonitorDidRefetch?(monitor.bridgeToObjectiveC)
}
)
swift.registerObserver(
observer,
didInsertObject: { (observer, monitor, object, toIndexPath) in
observer.listMonitor?(monitor.bridgeToObjectiveC, didInsertObject: object, toIndexPath: toIndexPath)
},
didDeleteObject: { (observer, monitor, object, fromIndexPath) in
observer.listMonitor?(monitor.bridgeToObjectiveC, didDeleteObject: object, fromIndexPath: fromIndexPath)
},
didUpdateObject: { (observer, monitor, object, atIndexPath) in
observer.listMonitor?(monitor.bridgeToObjectiveC, didUpdateObject: object, atIndexPath: atIndexPath)
},
didMoveObject: { (observer, monitor, object, fromIndexPath, toIndexPath) in
observer.listMonitor?(monitor.bridgeToObjectiveC, didMoveObject: object, fromIndexPath: fromIndexPath, toIndexPath: toIndexPath)
}
)
} }
/**
Registers a `CSListSectionObserver` to be notified when changes to the receiver's list occur.
To prevent retain-cycles, `CSListMonitor` only keeps `weak` references to its observers.
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
Calling `-addListSectionObserver:` multiple times on the same observer is safe, as `ListMonitor` unregisters previous notifications to the observer before re-registering them.
- parameter observer: a `CSListSectionObserver` to send change notifications to
*/
@objc @objc
public func addListSectionObserver(_ observer: CSListSectionObserver) { public func addListSectionObserver(_ observer: CSListSectionObserver) {
let swift = self.bridgeToSwift fatalError()
swift.unregisterObserver(observer)
swift.registerObserver(
observer,
willChange: { (observer, monitor) in
observer.listMonitorWillChange?(monitor.bridgeToObjectiveC)
},
didChange: { (observer, monitor) in
observer.listMonitorDidChange?(monitor.bridgeToObjectiveC)
},
willRefetch: { (observer, monitor) in
observer.listMonitorWillRefetch?(monitor.bridgeToObjectiveC)
},
didRefetch: { (observer, monitor) in
observer.listMonitorDidRefetch?(monitor.bridgeToObjectiveC)
}
)
swift.registerObserver(
observer,
didInsertObject: { (observer, monitor, object, toIndexPath) in
observer.listMonitor?(monitor.bridgeToObjectiveC, didInsertObject: object, toIndexPath: toIndexPath)
},
didDeleteObject: { (observer, monitor, object, fromIndexPath) in
observer.listMonitor?(monitor.bridgeToObjectiveC, didDeleteObject: object, fromIndexPath: fromIndexPath)
},
didUpdateObject: { (observer, monitor, object, atIndexPath) in
observer.listMonitor?(monitor.bridgeToObjectiveC, didUpdateObject: object, atIndexPath: atIndexPath)
},
didMoveObject: { (observer, monitor, object, fromIndexPath, toIndexPath) in
observer.listMonitor?(monitor.bridgeToObjectiveC, didMoveObject: object, fromIndexPath: fromIndexPath, toIndexPath: toIndexPath)
}
)
swift.registerObserver(
observer,
didInsertSection: { (observer, monitor, sectionInfo, toIndex) in
observer.listMonitor?(monitor.bridgeToObjectiveC, didInsertSection: sectionInfo, toSectionIndex: toIndex)
},
didDeleteSection: { (observer, monitor, sectionInfo, fromIndex) in
observer.listMonitor?(monitor.bridgeToObjectiveC, didDeleteSection: sectionInfo, fromSectionIndex: fromIndex)
}
)
} }
/**
Unregisters a `CSListObserver` from receiving notifications for changes to the receiver's list.
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
- parameter observer: a `CSListObserver` to unregister notifications to
*/
@objc @objc
public func removeListObserver(_ observer: CSListObserver) { public func removeListObserver(_ observer: CSListObserver) {
self.bridgeToSwift.unregisterObserver(observer) fatalError()
} }
// MARK: Public (Refetching) // MARK: Public (Refetching)
/**
Returns `YES` if a call to `-refetch:` was made to the `CSListMonitor` and is currently waiting for the fetching to complete. Returns `NO` otherwise.
*/
@objc @objc
public var isPendingRefetch: Bool { public var isPendingRefetch: Bool {
return self.bridgeToSwift.isPendingRefetch fatalError()
} }
/**
Asks the `CSListMonitor` to refetch its objects using the specified series of `CSFetchClause`s. Note that this method does not execute the fetch immediately; the actual fetching will happen after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes.
`refetch(...)` broadcasts `listMonitorWillRefetch(...)` to its observers immediately, and then `listMonitorDidRefetch(...)` after the new fetch request completes.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- Important: Starting CoreStore 4.0, all `CSFetchClause`s required by the `CSListMonitor` should be provided in the arguments list of `refetch(...)`.
*/
@objc @objc
public func refetch(_ fetchClauses: [CSFetchClause]) { public func refetch(_ fetchClauses: [CSFetchClause]) {
self.bridgeToSwift.refetch { (fetchRequest) in fatalError()
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
}
} }
@@ -511,21 +213,17 @@ public final class CSListMonitor: NSObject {
public override var hash: Int { public override var hash: Int {
return self.bridgeToSwift.hashValue fatalError()
} }
public override func isEqual(_ object: Any?) -> Bool { public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSListMonitor else { fatalError()
return false
}
return self.bridgeToSwift == object.bridgeToSwift
} }
public override var description: String { public override var description: String {
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)" fatalError()
} }
@@ -537,32 +235,20 @@ public final class CSListMonitor: NSObject {
@nonobjc @nonobjc
public required init<T: NSManagedObject>(_ swiftValue: ListMonitor<T>) { public required init<T: NSManagedObject>(_ swiftValue: ListMonitor<T>) {
self.bridgeToSwift = swiftValue.downcast() fatalError()
super.init()
} }
} }
// MARK: - ListMonitor // MARK: - ListMonitor
@available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
extension ListMonitor where ListMonitor.ObjectType: NSManagedObject { extension ListMonitor where ListMonitor.ObjectType: NSManagedObject {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
public var bridgeToObjectiveC: CSListMonitor { public var bridgeToObjectiveC: CSListMonitor {
return CSListMonitor(self) fatalError()
}
// MARK: FilePrivate
fileprivate func downcast() -> ListMonitor<NSManagedObject> {
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
return unsafeBitCast(x, to: type)
}
return noWarnUnsafeBitCast(self, to: ListMonitor<NSManagedObject>.self)
} }
} }
+3 -97
View File
@@ -29,49 +29,19 @@ import CoreData
// MARK: - CSListObserver // MARK: - CSListObserver
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
Implement the `CSListObserver` protocol to observe changes to a list of `NSManagedObject`s. `CSListObserver`s may register themselves to a `CSListMonitor`'s `-addListObserver:` method:
```
CSListMonitor *monitor = [CSCoreStore
monitorListFrom:[CSFrom entityClass:[MyPersonEntity class]]
fetchClauses:@[[CSOrderBy sortDescriptor:[CSSortKey withKeyPath:@"lastName" ascending:YES]]]];
[monitor addListObserver:self];
```
- SeeAlso: `ListObserver`
*/
@objc @objc
public protocol CSListObserver: AnyObject { public protocol CSListObserver: AnyObject {
/**
Handles processing just before a change to the observed list occurs
- parameter monitor: the `CSListMonitor` monitoring the list being observed
*/
@objc @objc
optional func listMonitorWillChange(_ monitor: CSListMonitor) optional func listMonitorWillChange(_ monitor: CSListMonitor)
/**
Handles processing right after a change to the observed list occurs
- parameter monitor: the `CSListMonitor` monitoring the object being observed
*/
@objc @objc
optional func listMonitorDidChange(_ monitor: CSListMonitor) optional func listMonitorDidChange(_ monitor: CSListMonitor)
/**
This method is broadcast from within the `CSListMonitor`'s `-refetchWithFetchClauses:` method to let observers prepare for the internal `NSFetchedResultsController`'s pending change to its predicate, sort descriptors, etc. Note that the actual refetch will happen after the `NSFetchedResultsController`'s last `-controllerDidChangeContent:` notification completes.
- parameter monitor: the `CSListMonitor` monitoring the object being observed
*/
@objc @objc
optional func listMonitorWillRefetch(_ monitor: CSListMonitor) optional func listMonitorWillRefetch(_ monitor: CSListMonitor)
/**
After the `CSListMonitor`'s `-refetchWithFetchClauses:` method is called, this method is broadcast after the `NSFetchedResultsController`'s last `-controllerDidChangeContent:` notification completes.
- parameter monitor: the `CSListMonitor` monitoring the object being observed
*/
@objc @objc
optional func listMonitorDidRefetch(_ monitor: CSListMonitor) optional func listMonitorDidRefetch(_ monitor: CSListMonitor)
} }
@@ -79,58 +49,19 @@ public protocol CSListObserver: AnyObject {
// MARK: - ListObjectObserver // MARK: - ListObjectObserver
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
Implement the `CSListObjectObserver` protocol to observe detailed changes to a list's object. `CSListObjectObserver`s may register themselves to a `CSListMonitor`'s `-addListObjectObserver(_:)` method:
```
CSListMonitor *monitor = [CSCoreStore
monitorListFrom:[CSFrom entityClass:[MyPersonEntity class]]
fetchClauses:@[[CSOrderBy sortDescriptor:[CSSortKey withKeyPath:@"lastName" ascending:YES]]]];
[monitor addListObjectObserver:self];
```
- SeeAlso: `ListObjectObserver`
*/
@objc @objc
public protocol CSListObjectObserver: CSListObserver { public protocol CSListObjectObserver: CSListObserver {
/**
Notifies that an object was inserted to the specified `NSIndexPath` in the list
- parameter monitor: the `CSListMonitor` monitoring the list being observed
- parameter object: the entity type for the inserted object
- parameter indexPath: the new `NSIndexPath` for the inserted object
*/
@objc @objc
optional func listMonitor(_ monitor: CSListMonitor, didInsertObject object: Any, toIndexPath indexPath: IndexPath) optional func listMonitor(_ monitor: CSListMonitor, didInsertObject object: Any, toIndexPath indexPath: IndexPath)
/**
Notifies that an object was deleted from the specified `NSIndexPath` in the list
- parameter monitor: the `CSListMonitor` monitoring the list being observed
- parameter object: the entity type for the deleted object
- parameter indexPath: the `NSIndexPath` for the deleted object
*/
@objc @objc
optional func listMonitor(_ monitor: CSListMonitor, didDeleteObject object: Any, fromIndexPath indexPath: IndexPath) optional func listMonitor(_ monitor: CSListMonitor, didDeleteObject object: Any, fromIndexPath indexPath: IndexPath)
/**
Notifies that an object at the specified `NSIndexPath` was updated
- parameter monitor: the `CSListMonitor` monitoring the list being observed
- parameter object: the entity type for the updated object
- parameter indexPath: the `NSIndexPath` for the updated object
*/
@objc @objc
optional func listMonitor(_ monitor: CSListMonitor, didUpdateObject object: Any, atIndexPath indexPath: IndexPath) optional func listMonitor(_ monitor: CSListMonitor, didUpdateObject object: Any, atIndexPath indexPath: IndexPath)
/**
Notifies that an object's index changed
- parameter monitor: the `CSListMonitor` monitoring the list being observed
- parameter object: the entity type for the moved object
- parameter fromIndexPath: the previous `NSIndexPath` for the moved object
- parameter toIndexPath: the new `NSIndexPath` for the moved object
*/
@objc @objc
optional func listMonitor(_ monitor: CSListMonitor, didMoveObject object: Any, fromIndexPath: IndexPath, toIndexPath: IndexPath) optional func listMonitor(_ monitor: CSListMonitor, didMoveObject object: Any, fromIndexPath: IndexPath, toIndexPath: IndexPath)
} }
@@ -138,38 +69,13 @@ public protocol CSListObjectObserver: CSListObserver {
// MARK: - CSListSectionObserver // MARK: - CSListSectionObserver
/** @available(*, unavailable, message: "CoreStore Objective-C is now obsoleted in preparation for Swift concurrency.")
Implement the `CSListSectionObserver` protocol to observe changes to a list's section info. `CSListSectionObserver`s may register themselves to a `CSListMonitor`'s `-addListSectionObserver:` method:
```
CSListMonitor *monitor = [CSCoreStore
monitorSectionedListFrom:[CSFrom entityClass:[MyPersonEntity class]]
sectionBy:[CSSectionBy keyPath:@"age"]
fetchClauses:@[[CSOrderBy sortDescriptor:[CSSortKey withKeyPath:@"lastName" ascending:YES]]]];
[monitor addListSectionObserver:self];
```
- SeeAlso: `ListSectionObserver`
*/
@objc @objc
public protocol CSListSectionObserver: CSListObjectObserver { public protocol CSListSectionObserver: CSListObjectObserver {
/**
Notifies that a section was inserted at the specified index
- parameter monitor: the `CSListMonitor` monitoring the list being observed
- parameter sectionInfo: the `NSFetchedResultsSectionInfo` for the inserted section
- parameter sectionIndex: the new section index for the new section
*/
@objc @objc
optional func listMonitor(_ monitor: CSListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) optional func listMonitor(_ monitor: CSListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int)
/**
Notifies that a section was inserted at the specified index
- parameter monitor: the `CSListMonitor` monitoring the list being observed
- parameter sectionInfo: the `NSFetchedResultsSectionInfo` for the deleted section
- parameter sectionIndex: the previous section index for the deleted section
*/
@objc @objc
optional func listMonitor(_ monitor: CSListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) optional func listMonitor(_ monitor: CSListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
} }

Some files were not shown because too many files have changed in this diff Show More