WIP: allow migrations for CoreStoreObjects

This commit is contained in:
John Estropia
2017-04-11 19:13:35 +09:00
parent e5ef4992d3
commit 9f3db61ff7
27 changed files with 1146 additions and 691 deletions

View File

@@ -63,7 +63,6 @@
82BA18D41C4BBD7100A0916E /* NSManagedObjectContext+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */; }; 82BA18D41C4BBD7100A0916E /* NSManagedObjectContext+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */; };
82BA18D51C4BBD7100A0916E /* NSManagedObjectContext+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */; }; 82BA18D51C4BBD7100A0916E /* NSManagedObjectContext+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */; };
82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */; }; 82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */; };
82BA18D71C4BBD7100A0916E /* NSManagedObjectModel+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */; };
82BA18D81C4BBD7100A0916E /* WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2D1AFF849C0064E85B /* WeakObject.swift */; }; 82BA18D81C4BBD7100A0916E /* WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2D1AFF849C0064E85B /* WeakObject.swift */; };
82BA18DC1C4BBD9C00A0916E /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; }; 82BA18DC1C4BBD9C00A0916E /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; };
82BA18DD1C4BBE1400A0916E /* NSFetchedResultsController+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */; }; 82BA18DD1C4BBE1400A0916E /* NSFetchedResultsController+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */; };
@@ -88,7 +87,14 @@
B51260801E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */; }; B51260801E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */; };
B51260811E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */; }; B51260811E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */; };
B51260821E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */; }; B51260821E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */; };
B51BE06A1B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */; }; B51260891E9B252B00402229 /* NSEntityDescription+DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */; };
B512608A1E9B252B00402229 /* NSEntityDescription+DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */; };
B512608B1E9B252B00402229 /* NSEntityDescription+DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */; };
B512608C1E9B252B00402229 /* NSEntityDescription+DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */; };
B51260931E9B28F100402229 /* EntityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51260921E9B28F100402229 /* EntityIdentifier.swift */; };
B51260941E9B28F100402229 /* EntityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51260921E9B28F100402229 /* EntityIdentifier.swift */; };
B51260951E9B28F100402229 /* EntityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51260921E9B28F100402229 /* EntityIdentifier.swift */; };
B51260961E9B28F100402229 /* EntityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51260921E9B28F100402229 /* EntityIdentifier.swift */; };
B51FE5AB1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */; }; B51FE5AB1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */; };
B51FE5AD1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */; }; B51FE5AD1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */; };
B51FE5AE1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */; }; B51FE5AE1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */; };
@@ -199,8 +205,27 @@
B52DD1C71BE1F94600949AFE /* NSManagedObjectContext+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */; }; B52DD1C71BE1F94600949AFE /* NSManagedObjectContext+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */; };
B52DD1C81BE1F94600949AFE /* NSManagedObjectContext+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */; }; B52DD1C81BE1F94600949AFE /* NSManagedObjectContext+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */; };
B52DD1C91BE1F94600949AFE /* NSManagedObjectContext+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */; }; B52DD1C91BE1F94600949AFE /* NSManagedObjectContext+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */; };
B52DD1CA1BE1F94600949AFE /* NSManagedObjectModel+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */; };
B52DD1CB1BE1F94600949AFE /* WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2D1AFF849C0064E85B /* WeakObject.swift */; }; B52DD1CB1BE1F94600949AFE /* WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2D1AFF849C0064E85B /* WeakObject.swift */; };
B52F742F1E9B50D0005F3DAC /* SchemaHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */; };
B52F74301E9B50D0005F3DAC /* SchemaHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */; };
B52F74311E9B50D0005F3DAC /* SchemaHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */; };
B52F74321E9B50D0005F3DAC /* SchemaHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */; };
B52F743D1E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; };
B52F743E1E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; };
B52F743F1E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; };
B52F74401E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; };
B52F74411E9B8724005F3DAC /* LegacyXcodeDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModel.swift */; };
B52F74421E9B8724005F3DAC /* LegacyXcodeDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModel.swift */; };
B52F74431E9B8724005F3DAC /* LegacyXcodeDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModel.swift */; };
B52F74441E9B8724005F3DAC /* LegacyXcodeDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModel.swift */; };
B52F74451E9B8724005F3DAC /* XcodeDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModel.swift */; };
B52F74461E9B8724005F3DAC /* XcodeDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModel.swift */; };
B52F74471E9B8724005F3DAC /* XcodeDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModel.swift */; };
B52F74481E9B8724005F3DAC /* XcodeDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModel.swift */; };
B52F744A1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */; };
B52F744B1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */; };
B52F744C1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */; };
B52F744D1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */; };
B52FD3AA1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */; }; B52FD3AA1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */; };
B52FD3AB1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */; }; B52FD3AB1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */; };
B52FD3AC1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */; }; B52FD3AC1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */; };
@@ -358,7 +383,6 @@
B56321B21BD6521C006C9394 /* NSManagedObjectContext+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */; }; B56321B21BD6521C006C9394 /* NSManagedObjectContext+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */; };
B56321B31BD6521C006C9394 /* NSManagedObjectContext+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */; }; B56321B31BD6521C006C9394 /* NSManagedObjectContext+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */; };
B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */; }; B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */; };
B56321B51BD6521C006C9394 /* NSManagedObjectModel+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */; };
B56321B61BD6521C006C9394 /* WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2D1AFF849C0064E85B /* WeakObject.swift */; }; B56321B61BD6521C006C9394 /* WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2D1AFF849C0064E85B /* WeakObject.swift */; };
B56507941D3930BC000596DA /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B56507931D3930BC000596DA /* CoreData.framework */; }; B56507941D3930BC000596DA /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B56507931D3930BC000596DA /* CoreData.framework */; };
B56507961D3930C1000596DA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B56507951D3930C1000596DA /* Foundation.framework */; }; B56507961D3930C1000596DA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B56507951D3930C1000596DA /* Foundation.framework */; };
@@ -417,10 +441,6 @@
B5C976E81C6E3A5D00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */; }; B5C976E81C6E3A5D00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */; };
B5C976E91C6E3A5E00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */; }; B5C976E91C6E3A5E00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */; };
B5D1E22C19FA9FBC003B2874 /* CoreStoreError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */; }; B5D1E22C19FA9FBC003B2874 /* CoreStoreError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */; };
B5D339AF1E925BF200C880DE /* DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339AE1E925BF200C880DE /* DynamicModel.swift */; };
B5D339B01E925BF200C880DE /* DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339AE1E925BF200C880DE /* DynamicModel.swift */; };
B5D339B11E925BF200C880DE /* DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339AE1E925BF200C880DE /* DynamicModel.swift */; };
B5D339B21E925BF200C880DE /* DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339AE1E925BF200C880DE /* DynamicModel.swift */; };
B5D339B41E925C2B00C880DE /* DynamicModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */; }; B5D339B41E925C2B00C880DE /* DynamicModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */; };
B5D339B51E925C2B00C880DE /* DynamicModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */; }; B5D339B51E925C2B00C880DE /* DynamicModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */; };
B5D339B61E925C2B00C880DE /* DynamicModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */; }; B5D339B61E925C2B00C880DE /* DynamicModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */; };
@@ -653,7 +673,8 @@
B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Setup.swift"; sourceTree = "<group>"; }; B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Setup.swift"; sourceTree = "<group>"; };
B509C7F31E54511B0061C547 /* ImportableAttributeType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportableAttributeType.swift; sourceTree = "<group>"; }; B509C7F31E54511B0061C547 /* ImportableAttributeType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportableAttributeType.swift; sourceTree = "<group>"; };
B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStoreObject+Convenience.swift"; sourceTree = "<group>"; }; B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStoreObject+Convenience.swift"; sourceTree = "<group>"; };
B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectModel+Setup.swift"; sourceTree = "<group>"; }; B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSEntityDescription+DynamicModel.swift"; sourceTree = "<group>"; };
B51260921E9B28F100402229 /* EntityIdentifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntityIdentifier.swift; sourceTree = "<group>"; };
B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+CustomDebugStringConvertible.swift"; sourceTree = "<group>"; }; B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+CustomDebugStringConvertible.swift"; sourceTree = "<group>"; };
B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFetchedResultsController+Convenience.swift"; sourceTree = "<group>"; }; B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFetchedResultsController+Convenience.swift"; sourceTree = "<group>"; };
B5220E071D0C5F8D009BC71E /* ObjectObserverTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectObserverTests.swift; sourceTree = "<group>"; }; B5220E071D0C5F8D009BC71E /* ObjectObserverTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectObserverTests.swift; sourceTree = "<group>"; };
@@ -671,6 +692,11 @@
B529C2031CA4A2DB007E7EBD /* CSSaveResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSaveResult.swift; sourceTree = "<group>"; }; B529C2031CA4A2DB007E7EBD /* CSSaveResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSaveResult.swift; sourceTree = "<group>"; };
B52DD1741BE1F8CC00949AFE /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B52DD1741BE1F8CC00949AFE /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B52DD17D1BE1F8CC00949AFE /* CoreStoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreStoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; B52DD17D1BE1F8CC00949AFE /* CoreStoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreStoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaHistory.swift; sourceTree = "<group>"; };
B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicSchema.swift; sourceTree = "<group>"; };
B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyXcodeDataModel.swift; sourceTree = "<group>"; };
B52F743C1E9B8724005F3DAC /* XcodeDataModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XcodeDataModel.swift; sourceTree = "<group>"; };
B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreSchema.swift; sourceTree = "<group>"; };
B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Logging.swift"; sourceTree = "<group>"; }; B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Logging.swift"; sourceTree = "<group>"; };
B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DispatchQueue+CoreStore.swift"; sourceTree = "<group>"; }; B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DispatchQueue+CoreStore.swift"; sourceTree = "<group>"; };
B538BA701D15B3E30003A766 /* CoreStoreBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreStoreBridge.m; sourceTree = "<group>"; }; B538BA701D15B3E30003A766 /* CoreStoreBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreStoreBridge.m; sourceTree = "<group>"; };
@@ -733,7 +759,6 @@
B5C976E21C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UnsafeDataTransaction+Observing.swift"; sourceTree = "<group>"; }; B5C976E21C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UnsafeDataTransaction+Observing.swift"; sourceTree = "<group>"; };
B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreFetchedResultsController.swift; sourceTree = "<group>"; }; B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreFetchedResultsController.swift; sourceTree = "<group>"; };
B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreError.swift; sourceTree = "<group>"; }; B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreError.swift; sourceTree = "<group>"; };
B5D339AE1E925BF200C880DE /* DynamicModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicModel.swift; sourceTree = "<group>"; };
B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicModelTests.swift; sourceTree = "<group>"; }; B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicModelTests.swift; sourceTree = "<group>"; };
B5D339D71E9489AB00C880DE /* CoreStoreObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreObject.swift; sourceTree = "<group>"; }; B5D339D71E9489AB00C880DE /* CoreStoreObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreObject.swift; sourceTree = "<group>"; };
B5D339DC1E9489C700C880DE /* DynamicObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicObject.swift; sourceTree = "<group>"; }; B5D339DC1E9489C700C880DE /* DynamicObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicObject.swift; sourceTree = "<group>"; };
@@ -1012,6 +1037,17 @@
name = Observing; name = Observing;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
B52F74391E9B8724005F3DAC /* Dynamic Schema */ = {
isa = PBXGroup;
children = (
B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */,
B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */,
B52F743C1E9B8724005F3DAC /* XcodeDataModel.swift */,
B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModel.swift */,
);
path = "Dynamic Schema";
sourceTree = "<group>";
};
B53FBA101CAB607000F0D40A /* Convenience */ = { B53FBA101CAB607000F0D40A /* Convenience */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -1092,8 +1128,9 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
B5D339D71E9489AB00C880DE /* CoreStoreObject.swift */, B5D339D71E9489AB00C880DE /* CoreStoreObject.swift */,
B5D339AE1E925BF200C880DE /* DynamicModel.swift */, B52F74391E9B8724005F3DAC /* Dynamic Schema */,
B5D339DC1E9489C700C880DE /* DynamicObject.swift */, B5D339DC1E9489C700C880DE /* DynamicObject.swift */,
B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */,
B5D339E61E9493A500C880DE /* Entity.swift */, B5D339E61E9493A500C880DE /* Entity.swift */,
B5D33A001E96012400C880DE /* Relationship.swift */, B5D33A001E96012400C880DE /* Relationship.swift */,
B5D339E11E948C3600C880DE /* Value.swift */, B5D339E11E948C3600C880DE /* Value.swift */,
@@ -1289,6 +1326,8 @@
children = ( children = (
B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */, B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */,
B526613F1CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift */, B526613F1CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift */,
B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */,
B51260921E9B28F100402229 /* EntityIdentifier.swift */,
B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */, B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */,
B5E834BA1B7691F3001D3D50 /* Functions.swift */, B5E834BA1B7691F3001D3D50 /* Functions.swift */,
B5FAD6AB1B51285300714891 /* MigrationManager.swift */, B5FAD6AB1B51285300714891 /* MigrationManager.swift */,
@@ -1299,7 +1338,6 @@
B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */, B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */,
B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */, B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */,
B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */, B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */,
B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */,
B5FEC18D1C9166E200532541 /* NSPersistentStore+Setup.swift */, B5FEC18D1C9166E200532541 /* NSPersistentStore+Setup.swift */,
B59AFF401C6593E400C0ABE2 /* NSPersistentStoreCoordinator+Setup.swift */, B59AFF401C6593E400C0ABE2 /* NSPersistentStoreCoordinator+Setup.swift */,
B5E84F2D1AFF849C0064E85B /* WeakObject.swift */, B5E84F2D1AFF849C0064E85B /* WeakObject.swift */,
@@ -1633,6 +1671,7 @@
B5ECDBF91CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */, B5ECDBF91CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */,
B5C976E71C6E3A5A00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */, B5C976E71C6E3A5A00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */,
B5F1DA901B9AA991007C5CBB /* ImportableUniqueObject.swift in Sources */, B5F1DA901B9AA991007C5CBB /* ImportableUniqueObject.swift in Sources */,
B51260891E9B252B00402229 /* NSEntityDescription+DynamicModel.swift in Sources */,
B504D0D61B02362500B2BBB1 /* CoreStore+Setup.swift in Sources */, B504D0D61B02362500B2BBB1 /* CoreStore+Setup.swift in Sources */,
B529C2041CA4A2DB007E7EBD /* CSSaveResult.swift in Sources */, B529C2041CA4A2DB007E7EBD /* CSSaveResult.swift in Sources */,
B5D1E22C19FA9FBC003B2874 /* CoreStoreError.swift in Sources */, B5D1E22C19FA9FBC003B2874 /* CoreStoreError.swift in Sources */,
@@ -1645,6 +1684,7 @@
B5E1B5981CAA0C23007FD580 /* CSObjectObserver.swift in Sources */, B5E1B5981CAA0C23007FD580 /* CSObjectObserver.swift in Sources */,
B5519A5F1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */, B5519A5F1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
B52FD3AA1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */, B52FD3AA1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74411E9B8724005F3DAC /* LegacyXcodeDataModel.swift in Sources */,
B51FE5AB1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */, B51FE5AB1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
B54A6A551BA15F2A007870FD /* FetchedResultsControllerDelegate.swift in Sources */, B54A6A551BA15F2A007870FD /* FetchedResultsControllerDelegate.swift in Sources */,
B5D339E21E948C3600C880DE /* Value.swift in Sources */, B5D339E21E948C3600C880DE /* Value.swift in Sources */,
@@ -1676,6 +1716,7 @@
B546F9731C9C553300D5AC55 /* SetupResult.swift in Sources */, B546F9731C9C553300D5AC55 /* SetupResult.swift in Sources */,
B56007111B3F6BD500A9A8F9 /* Into.swift in Sources */, B56007111B3F6BD500A9A8F9 /* Into.swift in Sources */,
B5E84F111AFF847B0064E85B /* Select.swift in Sources */, B5E84F111AFF847B0064E85B /* Select.swift in Sources */,
B51260931E9B28F100402229 /* EntityIdentifier.swift in Sources */,
B5FE4DA21C8481E100FA6A91 /* StorageInterface.swift in Sources */, B5FE4DA21C8481E100FA6A91 /* StorageInterface.swift in Sources */,
B53FB9FE1CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */, B53FB9FE1CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */,
B5DBE2D21C991B3E00B5CEFA /* CSDataStack.swift in Sources */, B5DBE2D21C991B3E00B5CEFA /* CSDataStack.swift in Sources */,
@@ -1696,6 +1737,7 @@
B5ECDC111CA816E500C7F112 /* CSTweak.swift in Sources */, B5ECDC111CA816E500C7F112 /* CSTweak.swift in Sources */,
B5E84F411AFF8CCD0064E85B /* ClauseTypes.swift in Sources */, B5E84F411AFF8CCD0064E85B /* ClauseTypes.swift in Sources */,
B5E84F0D1AFF847B0064E85B /* BaseDataTransaction+Querying.swift in Sources */, B5E84F0D1AFF847B0064E85B /* BaseDataTransaction+Querying.swift in Sources */,
B52F74451E9B8724005F3DAC /* XcodeDataModel.swift in Sources */,
B5FAD6AC1B51285300714891 /* MigrationManager.swift in Sources */, B5FAD6AC1B51285300714891 /* MigrationManager.swift in Sources */,
B5E84EF61AFF846E0064E85B /* DataStack+Transaction.swift in Sources */, B5E84EF61AFF846E0064E85B /* DataStack+Transaction.swift in Sources */,
B5FEC18E1C9166E200532541 /* NSPersistentStore+Setup.swift in Sources */, B5FEC18E1C9166E200532541 /* NSPersistentStore+Setup.swift in Sources */,
@@ -1711,6 +1753,7 @@
B5A5F2661CAEC50F004AB9AF /* CSSelect.swift in Sources */, B5A5F2661CAEC50F004AB9AF /* CSSelect.swift in Sources */,
B5ECDBE51CA6BEA300C7F112 /* CSClauseTypes.swift in Sources */, B5ECDBE51CA6BEA300C7F112 /* CSClauseTypes.swift in Sources */,
B5519A4A1CA1F4FB002BEF78 /* CSError.swift in Sources */, B5519A4A1CA1F4FB002BEF78 /* CSError.swift in Sources */,
B52F742F1E9B50D0005F3DAC /* SchemaHistory.swift in Sources */,
B5E84EF51AFF846E0064E85B /* BaseDataTransaction.swift in Sources */, B5E84EF51AFF846E0064E85B /* BaseDataTransaction.swift in Sources */,
B5E84EFB1AFF846E0064E85B /* SaveResult.swift in Sources */, B5E84EFB1AFF846E0064E85B /* SaveResult.swift in Sources */,
B5D339EC1E9495E500C880DE /* Attribute+Querying.swift in Sources */, B5D339EC1E9495E500C880DE /* Attribute+Querying.swift in Sources */,
@@ -1719,8 +1762,7 @@
B5E84EFC1AFF846E0064E85B /* SynchronousDataTransaction.swift in Sources */, B5E84EFC1AFF846E0064E85B /* SynchronousDataTransaction.swift in Sources */,
B5E222231CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */, B5E222231CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */,
B5E84F281AFF84920064E85B /* NSManagedObject+Convenience.swift in Sources */, B5E84F281AFF84920064E85B /* NSManagedObject+Convenience.swift in Sources */,
B51BE06A1B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift in Sources */, B52F744A1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */,
B5D339AF1E925BF200C880DE /* DynamicModel.swift in Sources */,
B5AEFAB51C9962AE00AD137F /* CoreStoreBridge.swift in Sources */, B5AEFAB51C9962AE00AD137F /* CoreStoreBridge.swift in Sources */,
B5E2222A1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */, B5E2222A1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */,
B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */, B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */,
@@ -1744,6 +1786,7 @@
B5E84F211AFF84860064E85B /* CoreStore+Observing.swift in Sources */, B5E84F211AFF84860064E85B /* CoreStore+Observing.swift in Sources */,
B559CD431CAA8B6300E4D58B /* CSSetupResult.swift in Sources */, B559CD431CAA8B6300E4D58B /* CSSetupResult.swift in Sources */,
B5FE4DA71C84FB4400FA6A91 /* InMemoryStore.swift in Sources */, B5FE4DA71C84FB4400FA6A91 /* InMemoryStore.swift in Sources */,
B52F743D1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
B5ECDBEC1CA6BF2000C7F112 /* CSFrom.swift in Sources */, B5ECDBEC1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
B5E834B91B76311F001D3D50 /* BaseDataTransaction+Importing.swift in Sources */, B5E834B91B76311F001D3D50 /* BaseDataTransaction+Importing.swift in Sources */,
B5E84EE61AFF84610064E85B /* DefaultLogger.swift in Sources */, B5E84EE61AFF84610064E85B /* DefaultLogger.swift in Sources */,
@@ -1799,6 +1842,7 @@
B5ECDBFB1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */, B5ECDBFB1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */,
B5C976E81C6E3A5D00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */, B5C976E81C6E3A5D00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */,
82BA18A21C4BBD1D00A0916E /* CoreStoreError.swift in Sources */, 82BA18A21C4BBD1D00A0916E /* CoreStoreError.swift in Sources */,
B512608A1E9B252B00402229 /* NSEntityDescription+DynamicModel.swift in Sources */,
82BA18B21C4BBD3900A0916E /* ImportableObject.swift in Sources */, 82BA18B21C4BBD3900A0916E /* ImportableObject.swift in Sources */,
B529C2061CA4A2DB007E7EBD /* CSSaveResult.swift in Sources */, B529C2061CA4A2DB007E7EBD /* CSSaveResult.swift in Sources */,
82BA18AE1C4BBD3100A0916E /* DataStack+Transaction.swift in Sources */, 82BA18AE1C4BBD3100A0916E /* DataStack+Transaction.swift in Sources */,
@@ -1811,6 +1855,7 @@
B5E1B59A1CAA0C23007FD580 /* CSObjectObserver.swift in Sources */, B5E1B59A1CAA0C23007FD580 /* CSObjectObserver.swift in Sources */,
B5519A601CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */, B5519A601CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
B52FD3AB1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */, B52FD3AB1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74421E9B8724005F3DAC /* LegacyXcodeDataModel.swift in Sources */,
B51FE5AD1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */, B51FE5AD1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
B5FE4DAD1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */, B5FE4DAD1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */,
B5D339E31E948C3600C880DE /* Value.swift in Sources */, B5D339E31E948C3600C880DE /* Value.swift in Sources */,
@@ -1842,6 +1887,7 @@
B546F9741C9C553300D5AC55 /* SetupResult.swift in Sources */, B546F9741C9C553300D5AC55 /* SetupResult.swift in Sources */,
82BA18B11C4BBD3100A0916E /* SaveResult.swift in Sources */, 82BA18B11C4BBD3100A0916E /* SaveResult.swift in Sources */,
82BA18DD1C4BBE1400A0916E /* NSFetchedResultsController+Convenience.swift in Sources */, 82BA18DD1C4BBE1400A0916E /* NSFetchedResultsController+Convenience.swift in Sources */,
B51260941E9B28F100402229 /* EntityIdentifier.swift in Sources */,
B5FE4DA81C84FB4400FA6A91 /* InMemoryStore.swift in Sources */, B5FE4DA81C84FB4400FA6A91 /* InMemoryStore.swift in Sources */,
B53FBA001CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */, B53FBA001CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */,
B5DBE2D31C991B3E00B5CEFA /* CSDataStack.swift in Sources */, B5DBE2D31C991B3E00B5CEFA /* CSDataStack.swift in Sources */,
@@ -1862,6 +1908,7 @@
B5ECDC131CA816E500C7F112 /* CSTweak.swift in Sources */, B5ECDC131CA816E500C7F112 /* CSTweak.swift in Sources */,
82BA18C91C4BBD5900A0916E /* MigrationType.swift in Sources */, 82BA18C91C4BBD5900A0916E /* MigrationType.swift in Sources */,
82BA18D01C4BBD7100A0916E /* MigrationManager.swift in Sources */, 82BA18D01C4BBD7100A0916E /* MigrationManager.swift in Sources */,
B52F74461E9B8724005F3DAC /* XcodeDataModel.swift in Sources */,
82BA18C61C4BBD5900A0916E /* DataStack+Migration.swift in Sources */, 82BA18C61C4BBD5900A0916E /* DataStack+Migration.swift in Sources */,
B59851491C90289D00C99590 /* NSPersistentStoreCoordinator+Setup.swift in Sources */, B59851491C90289D00C99590 /* NSPersistentStoreCoordinator+Setup.swift in Sources */,
B5E1B5A41CAA4365007FD580 /* CSCoreStore+Observing.swift in Sources */, B5E1B5A41CAA4365007FD580 /* CSCoreStore+Observing.swift in Sources */,
@@ -1876,7 +1923,7 @@
B5D339DE1E9489C700C880DE /* DynamicObject.swift in Sources */, B5D339DE1E9489C700C880DE /* DynamicObject.swift in Sources */,
B5ECDBE71CA6BEA300C7F112 /* CSClauseTypes.swift in Sources */, B5ECDBE71CA6BEA300C7F112 /* CSClauseTypes.swift in Sources */,
B5519A4B1CA1F4FB002BEF78 /* CSError.swift in Sources */, B5519A4B1CA1F4FB002BEF78 /* CSError.swift in Sources */,
82BA18D71C4BBD7100A0916E /* NSManagedObjectModel+Setup.swift in Sources */, B52F74301E9B50D0005F3DAC /* SchemaHistory.swift in Sources */,
82BA18C31C4BBD5300A0916E /* ObjectObserver.swift in Sources */, 82BA18C31C4BBD5300A0916E /* ObjectObserver.swift in Sources */,
82BA18BF1C4BBD5300A0916E /* SectionBy.swift in Sources */, 82BA18BF1C4BBD5300A0916E /* SectionBy.swift in Sources */,
B5D339ED1E9495E500C880DE /* Attribute+Querying.swift in Sources */, B5D339ED1E9495E500C880DE /* Attribute+Querying.swift in Sources */,
@@ -1885,8 +1932,8 @@
B5E222251CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */, B5E222251CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */,
82BA18C41C4BBD5300A0916E /* ListMonitor.swift in Sources */, 82BA18C41C4BBD5300A0916E /* ListMonitor.swift in Sources */,
82BA18BA1C4BBD4A00A0916E /* Select.swift in Sources */, 82BA18BA1C4BBD4A00A0916E /* Select.swift in Sources */,
B52F744B1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */,
B5AEFAB61C9962AE00AD137F /* CoreStoreBridge.swift in Sources */, B5AEFAB61C9962AE00AD137F /* CoreStoreBridge.swift in Sources */,
B5D339B01E925BF200C880DE /* DynamicModel.swift in Sources */,
B5E2222C1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */, B5E2222C1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */,
82BA18A71C4BBD2900A0916E /* CoreStore+Logging.swift in Sources */, 82BA18A71C4BBD2900A0916E /* CoreStore+Logging.swift in Sources */,
82BA18D81C4BBD7100A0916E /* WeakObject.swift in Sources */, 82BA18D81C4BBD7100A0916E /* WeakObject.swift in Sources */,
@@ -1910,6 +1957,7 @@
B559CD451CAA8B6300E4D58B /* CSSetupResult.swift in Sources */, B559CD451CAA8B6300E4D58B /* CSSetupResult.swift in Sources */,
82BA18B81C4BBD4200A0916E /* ClauseTypes.swift in Sources */, 82BA18B81C4BBD4200A0916E /* ClauseTypes.swift in Sources */,
B5ECDBEE1CA6BF2000C7F112 /* CSFrom.swift in Sources */, B5ECDBEE1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
B52F743E1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */, 82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */,
82BA18B91C4BBD4A00A0916E /* From.swift in Sources */, 82BA18B91C4BBD4A00A0916E /* From.swift in Sources */,
B53FBA061CAB300C00F0D40A /* CSMigrationType.swift in Sources */, B53FBA061CAB300C00F0D40A /* CSMigrationType.swift in Sources */,
@@ -1965,6 +2013,7 @@
B5DBE2D01C9914A900B5CEFA /* CSCoreStore.swift in Sources */, B5DBE2D01C9914A900B5CEFA /* CSCoreStore.swift in Sources */,
B5677D411CD3B1E400322BFC /* ICloudStoreObserver.swift in Sources */, B5677D411CD3B1E400322BFC /* ICloudStoreObserver.swift in Sources */,
B52DD1BE1BE1F94300949AFE /* Progress+Convenience.swift in Sources */, B52DD1BE1BE1F94300949AFE /* Progress+Convenience.swift in Sources */,
B512608C1E9B252B00402229 /* NSEntityDescription+DynamicModel.swift in Sources */,
B5ECDC151CA816E500C7F112 /* CSTweak.swift in Sources */, B5ECDC151CA816E500C7F112 /* CSTweak.swift in Sources */,
B546F9761C9C553300D5AC55 /* SetupResult.swift in Sources */, B546F9761C9C553300D5AC55 /* SetupResult.swift in Sources */,
B53FBA161CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */, B53FBA161CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
@@ -1977,6 +2026,7 @@
B5ECDC211CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */, B5ECDC211CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */,
B52DD1C21BE1F94600949AFE /* MigrationManager.swift in Sources */, B52DD1C21BE1F94600949AFE /* MigrationManager.swift in Sources */,
B52FD3AD1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */, B52FD3AD1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74441E9B8724005F3DAC /* LegacyXcodeDataModel.swift in Sources */,
B5ECDC2D1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */, B5ECDC2D1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */,
B5D7A5BA1CA3BF8F005C752B /* CSInto.swift in Sources */, B5D7A5BA1CA3BF8F005C752B /* CSInto.swift in Sources */,
B5D339E51E948C3600C880DE /* Value.swift in Sources */, B5D339E51E948C3600C880DE /* Value.swift in Sources */,
@@ -2008,6 +2058,7 @@
B52DD1BD1BE1F94300949AFE /* NSManagedObject+Convenience.swift in Sources */, B52DD1BD1BE1F94300949AFE /* NSManagedObject+Convenience.swift in Sources */,
B52DD1AD1BE1F93900949AFE /* Where.swift in Sources */, B52DD1AD1BE1F93900949AFE /* Where.swift in Sources */,
B53FBA1C1CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift in Sources */, B53FBA1C1CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift in Sources */,
B51260961E9B28F100402229 /* EntityIdentifier.swift in Sources */,
B5ECDBE31CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift in Sources */, B5ECDBE31CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift in Sources */,
B5ECDC031CA80CBA00C7F112 /* CSWhere.swift in Sources */, B5ECDC031CA80CBA00C7F112 /* CSWhere.swift in Sources */,
B52DD1AC1BE1F93900949AFE /* Select.swift in Sources */, B52DD1AC1BE1F93900949AFE /* Select.swift in Sources */,
@@ -2028,6 +2079,7 @@
B5ECDC091CA8138100C7F112 /* CSOrderBy.swift in Sources */, B5ECDC091CA8138100C7F112 /* CSOrderBy.swift in Sources */,
B52DD1A51BE1F92F00949AFE /* ImportableUniqueObject.swift in Sources */, B52DD1A51BE1F92F00949AFE /* ImportableUniqueObject.swift in Sources */,
B5E222271CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */, B5E222271CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */,
B52F74481E9B8724005F3DAC /* XcodeDataModel.swift in Sources */,
B5519A621CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */, B5519A621CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
B52DD19C1BE1F92C00949AFE /* Into.swift in Sources */, B52DD19C1BE1F92C00949AFE /* Into.swift in Sources */,
B5FE4DA51C8481E100FA6A91 /* StorageInterface.swift in Sources */, B5FE4DA51C8481E100FA6A91 /* StorageInterface.swift in Sources */,
@@ -2036,13 +2088,13 @@
B5FE4DAA1C84FB4400FA6A91 /* InMemoryStore.swift in Sources */, B5FE4DAA1C84FB4400FA6A91 /* InMemoryStore.swift in Sources */,
B52DD1AF1BE1F93900949AFE /* GroupBy.swift in Sources */, B52DD1AF1BE1F93900949AFE /* GroupBy.swift in Sources */,
B52DD1B01BE1F93900949AFE /* Tweak.swift in Sources */, B52DD1B01BE1F93900949AFE /* Tweak.swift in Sources */,
B52DD1CA1BE1F94600949AFE /* NSManagedObjectModel+Setup.swift in Sources */,
B52DD1A41BE1F92F00949AFE /* ImportableObject.swift in Sources */, B52DD1A41BE1F92F00949AFE /* ImportableObject.swift in Sources */,
B5220E161D13067C009BC71E /* ObjectMonitor.swift in Sources */, B5220E161D13067C009BC71E /* ObjectMonitor.swift in Sources */,
B5D339E01E9489C700C880DE /* DynamicObject.swift in Sources */, B5D339E01E9489C700C880DE /* DynamicObject.swift in Sources */,
B52DD1AE1BE1F93900949AFE /* OrderBy.swift in Sources */, B52DD1AE1BE1F93900949AFE /* OrderBy.swift in Sources */,
B52DD1BA1BE1F94000949AFE /* MigrationChain.swift in Sources */, B52DD1BA1BE1F94000949AFE /* MigrationChain.swift in Sources */,
B50392FB1C479640009900CA /* NSManagedObject+Transaction.swift in Sources */, B50392FB1C479640009900CA /* NSManagedObject+Transaction.swift in Sources */,
B52F74321E9B50D0005F3DAC /* SchemaHistory.swift in Sources */,
B52DD1A31BE1F92C00949AFE /* SaveResult.swift in Sources */, B52DD1A31BE1F92C00949AFE /* SaveResult.swift in Sources */,
B5220E211D130816009BC71E /* CSObjectObserver.swift in Sources */, B5220E211D130816009BC71E /* CSObjectObserver.swift in Sources */,
B5D339EF1E9495E500C880DE /* Attribute+Querying.swift in Sources */, B5D339EF1E9495E500C880DE /* Attribute+Querying.swift in Sources */,
@@ -2051,8 +2103,8 @@
B52DD1C11BE1F94600949AFE /* Functions.swift in Sources */, B52DD1C11BE1F94600949AFE /* Functions.swift in Sources */,
B5220E1A1D130791009BC71E /* CoreStoreFetchedResultsController.swift in Sources */, B5220E1A1D130791009BC71E /* CoreStoreFetchedResultsController.swift in Sources */,
B53FBA0F1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */, B53FBA0F1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */,
B52F744D1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */,
B59FA0B21CCBACA8007C9BCA /* ICloudStore.swift in Sources */, B59FA0B21CCBACA8007C9BCA /* ICloudStore.swift in Sources */,
B5D339B21E925BF200C880DE /* DynamicModel.swift in Sources */,
B52DD19A1BE1F92800949AFE /* CoreStore+Logging.swift in Sources */, B52DD19A1BE1F92800949AFE /* CoreStore+Logging.swift in Sources */,
B52DD1A71BE1F93200949AFE /* BaseDataTransaction+Querying.swift in Sources */, B52DD1A71BE1F93200949AFE /* BaseDataTransaction+Querying.swift in Sources */,
B546F96C1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, B546F96C1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
@@ -2076,6 +2128,7 @@
B52DD19B1BE1F92800949AFE /* CoreStoreLogger.swift in Sources */, B52DD19B1BE1F92800949AFE /* CoreStoreLogger.swift in Sources */,
B52DD1991BE1F92800949AFE /* DefaultLogger.swift in Sources */, B52DD1991BE1F92800949AFE /* DefaultLogger.swift in Sources */,
B5220E201D130813009BC71E /* CSObjectMonitor.swift in Sources */, B5220E201D130813009BC71E /* CSObjectMonitor.swift in Sources */,
B52F74401E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
B5220E171D1306DF009BC71E /* UnsafeDataTransaction+Observing.swift in Sources */, B5220E171D1306DF009BC71E /* UnsafeDataTransaction+Observing.swift in Sources */,
B53FBA081CAB300C00F0D40A /* CSMigrationType.swift in Sources */, B53FBA081CAB300C00F0D40A /* CSMigrationType.swift in Sources */,
B52DD1B91BE1F94000949AFE /* CoreStore+Migration.swift in Sources */, B52DD1B91BE1F94000949AFE /* CoreStore+Migration.swift in Sources */,
@@ -2131,6 +2184,7 @@
B5ECDBFC1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */, B5ECDBFC1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */,
B5C976E91C6E3A5E00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */, B5C976E91C6E3A5E00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */,
B56321801BD65216006C9394 /* CoreStoreError.swift in Sources */, B56321801BD65216006C9394 /* CoreStoreError.swift in Sources */,
B512608B1E9B252B00402229 /* NSEntityDescription+DynamicModel.swift in Sources */,
B56321AD1BD6521C006C9394 /* MigrationManager.swift in Sources */, B56321AD1BD6521C006C9394 /* MigrationManager.swift in Sources */,
B529C2071CA4A2DC007E7EBD /* CSSaveResult.swift in Sources */, B529C2071CA4A2DC007E7EBD /* CSSaveResult.swift in Sources */,
B563219D1BD65216006C9394 /* DataStack+Observing.swift in Sources */, B563219D1BD65216006C9394 /* DataStack+Observing.swift in Sources */,
@@ -2143,6 +2197,7 @@
B5519A611CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */, B5519A611CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
B5FE4DAE1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */, B5FE4DAE1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */,
B52FD3AC1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */, B52FD3AC1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74431E9B8724005F3DAC /* LegacyXcodeDataModel.swift in Sources */,
B51FE5AE1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */, B51FE5AE1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
B563218C1BD65216006C9394 /* DataStack+Transaction.swift in Sources */, B563218C1BD65216006C9394 /* DataStack+Transaction.swift in Sources */,
B5D339E41E948C3600C880DE /* Value.swift in Sources */, B5D339E41E948C3600C880DE /* Value.swift in Sources */,
@@ -2174,6 +2229,7 @@
B56321981BD65216006C9394 /* Where.swift in Sources */, B56321981BD65216006C9394 /* Where.swift in Sources */,
B5202CFD1C046E8400DED140 /* NSFetchedResultsController+Convenience.swift in Sources */, B5202CFD1C046E8400DED140 /* NSFetchedResultsController+Convenience.swift in Sources */,
B5FE4DA91C84FB4400FA6A91 /* InMemoryStore.swift in Sources */, B5FE4DA91C84FB4400FA6A91 /* InMemoryStore.swift in Sources */,
B51260951E9B28F100402229 /* EntityIdentifier.swift in Sources */,
B53FBA011CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */, B53FBA011CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */,
B5DBE2D41C991B3E00B5CEFA /* CSDataStack.swift in Sources */, B5DBE2D41C991B3E00B5CEFA /* CSDataStack.swift in Sources */,
B50392FA1C47963F009900CA /* NSManagedObject+Transaction.swift in Sources */, B50392FA1C47963F009900CA /* NSManagedObject+Transaction.swift in Sources */,
@@ -2194,6 +2250,7 @@
B56321931BD65216006C9394 /* DataStack+Querying.swift in Sources */, B56321931BD65216006C9394 /* DataStack+Querying.swift in Sources */,
B56321A71BD65216006C9394 /* MigrationResult.swift in Sources */, B56321A71BD65216006C9394 /* MigrationResult.swift in Sources */,
B598514A1C90289E00C99590 /* NSPersistentStoreCoordinator+Setup.swift in Sources */, B598514A1C90289E00C99590 /* NSPersistentStoreCoordinator+Setup.swift in Sources */,
B52F74471E9B8724005F3DAC /* XcodeDataModel.swift in Sources */,
B5FEC1901C9166E700532541 /* NSPersistentStore+Setup.swift in Sources */, B5FEC1901C9166E700532541 /* NSPersistentStore+Setup.swift in Sources */,
B56321A11BD65216006C9394 /* ListMonitor.swift in Sources */, B56321A11BD65216006C9394 /* ListMonitor.swift in Sources */,
B5E1B5A51CAA4365007FD580 /* CSCoreStore+Observing.swift in Sources */, B5E1B5A51CAA4365007FD580 /* CSCoreStore+Observing.swift in Sources */,
@@ -2208,7 +2265,7 @@
B5D339DF1E9489C700C880DE /* DynamicObject.swift in Sources */, B5D339DF1E9489C700C880DE /* DynamicObject.swift in Sources */,
B5519A4C1CA1F4FB002BEF78 /* CSError.swift in Sources */, B5519A4C1CA1F4FB002BEF78 /* CSError.swift in Sources */,
B563219B1BD65216006C9394 /* Tweak.swift in Sources */, B563219B1BD65216006C9394 /* Tweak.swift in Sources */,
B56321B51BD6521C006C9394 /* NSManagedObjectModel+Setup.swift in Sources */, B52F74311E9B50D0005F3DAC /* SchemaHistory.swift in Sources */,
B563218F1BD65216006C9394 /* ImportableObject.swift in Sources */, B563218F1BD65216006C9394 /* ImportableObject.swift in Sources */,
B56321991BD65216006C9394 /* OrderBy.swift in Sources */, B56321991BD65216006C9394 /* OrderBy.swift in Sources */,
B5D339EE1E9495E500C880DE /* Attribute+Querying.swift in Sources */, B5D339EE1E9495E500C880DE /* Attribute+Querying.swift in Sources */,
@@ -2217,8 +2274,8 @@
B5E222261CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */, B5E222261CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */,
B56321A21BD65216006C9394 /* ListObserver.swift in Sources */, B56321A21BD65216006C9394 /* ListObserver.swift in Sources */,
B563218A1BD65216006C9394 /* SynchronousDataTransaction.swift in Sources */, B563218A1BD65216006C9394 /* SynchronousDataTransaction.swift in Sources */,
B52F744C1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */,
B5AEFAB71C9962AE00AD137F /* CoreStoreBridge.swift in Sources */, B5AEFAB71C9962AE00AD137F /* CoreStoreBridge.swift in Sources */,
B5D339B11E925BF200C880DE /* DynamicModel.swift in Sources */,
B5E2222D1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */, B5E2222D1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */,
B563219F1BD65216006C9394 /* ObjectMonitor.swift in Sources */, B563219F1BD65216006C9394 /* ObjectMonitor.swift in Sources */,
B56321B61BD6521C006C9394 /* WeakObject.swift in Sources */, B56321B61BD6521C006C9394 /* WeakObject.swift in Sources */,
@@ -2242,6 +2299,7 @@
B559CD461CAA8B6300E4D58B /* CSSetupResult.swift in Sources */, B559CD461CAA8B6300E4D58B /* CSSetupResult.swift in Sources */,
B56321A61BD65216006C9394 /* MigrationType.swift in Sources */, B56321A61BD65216006C9394 /* MigrationType.swift in Sources */,
B5ECDBEF1CA6BF2000C7F112 /* CSFrom.swift in Sources */, B5ECDBEF1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
B52F743F1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */, B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */,
B56321861BD65216006C9394 /* CoreStoreLogger.swift in Sources */, B56321861BD65216006C9394 /* CoreStoreLogger.swift in Sources */,
B53FBA071CAB300C00F0D40A /* CSMigrationType.swift in Sources */, B53FBA071CAB300C00F0D40A /* CSMigrationType.swift in Sources */,

View File

@@ -60,7 +60,7 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
} }
for model in models { for model in models {
if model.version == storeVersion { if model.schemaHistory.currentModelVersion == storeVersion {
return model return model
} }
@@ -141,29 +141,35 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
// MARK: Private // MARK: Private
private typealias ModelMetadata = (label: String, version: String, entityType: NSManagedObject.Type, migrationChain: MigrationChain) private typealias ModelMetadata = (label: String, entityType: NSManagedObject.Type, schemaHistory: SchemaHistory)
private let models: [ModelMetadata] = [ private let models: [ModelMetadata] = [
( (
label: "Model V1", label: "Model V1",
version: "MigrationDemo",
entityType: OrganismV1.self, entityType: OrganismV1.self,
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"] schemaHistory: SchemaHistory(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
)
), ),
( (
label: "Model V2", label: "Model V2",
version: "MigrationDemoV2",
entityType: OrganismV2.self, entityType: OrganismV2.self,
migrationChain: [ schemaHistory: SchemaHistory(
"MigrationDemo": "MigrationDemoV2", modelName: "MigrationDemo",
"MigrationDemoV3": "MigrationDemoV2" migrationChain: [
] "MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
]
)
), ),
( (
label: "Model V3", label: "Model V3",
version: "MigrationDemoV3",
entityType: OrganismV3.self, entityType: OrganismV3.self,
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"] schemaHistory: SchemaHistory(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
)
) )
] ]
@@ -210,17 +216,14 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
private func selectModelVersion(_ model: ModelMetadata) { private func selectModelVersion(_ model: ModelMetadata) {
if self.dataStack?.modelVersion == model.version { if self.dataStack?.modelVersion == model.schemaHistory.currentModelVersion {
return return
} }
self.set(dataStack: nil, model: nil, scrollToSelection: false) // explicitly trigger NSPersistentStore cleanup by deallocating the stack self.set(dataStack: nil, model: nil, scrollToSelection: false) // explicitly trigger NSPersistentStore cleanup by deallocating the stack
let dataStack = DataStack( let dataStack = DataStack(schemaHistory: model.schemaHistory)
modelName: "MigrationDemo",
migrationChain: model.migrationChain
)
self.setEnabled(false) self.setEnabled(false)
let progress = dataStack.addStorage( let progress = dataStack.addStorage(
@@ -313,7 +316,13 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
if let dataStack = dataStack, let model = model { if let dataStack = dataStack, let model = model {
self.segmentedControl?.selectedSegmentIndex = self.models.map { $0.version }.index(of: model.version)! self.segmentedControl?.selectedSegmentIndex = self.models
.index(
where: { (_, _, schemaHistory) -> Bool in
schemaHistory.currentModelVersion == model.schemaHistory.currentModelVersion
}
)!
self._dataStack = dataStack self._dataStack = dataStack
let listMonitor = dataStack.monitorList(From(model.entityType), OrderBy(.descending("dna"))) let listMonitor = dataStack.monitorList(From(model.entityType), OrderBy(.descending("dna")))

View File

@@ -17,7 +17,7 @@ import CoreStore
class BaseTestDataTestCase: BaseTestCase { class BaseTestDataTestCase: BaseTestCase {
@nonobjc @nonobjc
let dateFormatter: DateFormatter = { let dateFormatter: DateFormatter = cs_lazy {
let formatter = DateFormatter() let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX") formatter.locale = Locale(identifier: "en_US_POSIX")
@@ -25,7 +25,7 @@ class BaseTestDataTestCase: BaseTestCase {
formatter.calendar = Calendar(identifier: Calendar.Identifier.gregorian) formatter.calendar = Calendar(identifier: Calendar.Identifier.gregorian)
formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ" formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"
return formatter return formatter
}() }
@nonobjc @nonobjc
func prepareTestDataForStack(_ stack: DataStack, configurations: [ModelConfiguration] = [nil]) { func prepareTestDataForStack(_ stack: DataStack, configurations: [ModelConfiguration] = [nil]) {

View File

@@ -57,8 +57,8 @@ class DynamicModelTests: BaseTestDataTestCase {
func testDynamicModels_CanBeDeclaredCorrectly() { func testDynamicModels_CanBeDeclaredCorrectly() {
let dataStack = DataStack( let dataStack = DataStack(
dynamicModel: DynamicModel( CoreStoreSchema(
version: "V1", modelVersion: "V1",
entities: [ entities: [
Entity<Animal>("Animal"), Entity<Animal>("Animal"),
Entity<Dog>("Dog"), Entity<Dog>("Dog"),

View File

@@ -85,16 +85,19 @@ final class ErrorTests: XCTestCase {
let dummyURL = URL(string: "file:///test1/test2.sqlite")! let dummyURL = URL(string: "file:///test1/test2.sqlite")!
let model = NSManagedObjectModel.fromBundle(Bundle(for: type(of: self)), modelName: "Model") let schemaHistory = SchemaHistory(
modelName: "Model",
bundle: Bundle(for: type(of: self))
)
let version = "1.0.0" let version = "1.0.0"
let error = CoreStoreError.mappingModelNotFound(localStoreURL: dummyURL, targetModel: model, targetModelVersion: version) let error = CoreStoreError.mappingModelNotFound(localStoreURL: dummyURL, targetModel: schemaHistory.rawModel, targetModelVersion: version)
XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain) XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.mappingModelNotFound.rawValue) XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
let userInfo: NSDictionary = [ let userInfo: NSDictionary = [
"localStoreURL": dummyURL, "localStoreURL": dummyURL,
"targetModel": model, "targetModel": schemaHistory.rawModel,
"targetModelVersion": version "targetModelVersion": version
] ]
let objcError = error.bridgeToObjectiveC let objcError = error.bridgeToObjectiveC

View File

@@ -37,8 +37,8 @@ final class MigrationChainTests: XCTestCase {
dynamic func test_ThatNilMigrationChains_HaveNoVersions() { dynamic func test_ThatNilMigrationChains_HaveNoVersions() {
let chain: MigrationChain = nil let chain: MigrationChain = nil
XCTAssertTrue(chain.valid) XCTAssertTrue(chain.isValid)
XCTAssertTrue(chain.empty) XCTAssertTrue(chain.isEmpty)
XCTAssertFalse(chain.contains("version1")) XCTAssertFalse(chain.contains("version1"))
XCTAssertNil(chain.nextVersionFrom("version1")) XCTAssertNil(chain.nextVersionFrom("version1"))
@@ -48,8 +48,8 @@ final class MigrationChainTests: XCTestCase {
dynamic func test_ThatStringMigrationChains_HaveOneVersion() { dynamic func test_ThatStringMigrationChains_HaveOneVersion() {
let chain: MigrationChain = "version1" let chain: MigrationChain = "version1"
XCTAssertTrue(chain.valid) XCTAssertTrue(chain.isValid)
XCTAssertTrue(chain.empty) XCTAssertTrue(chain.isEmpty)
XCTAssertTrue(chain.contains("version1")) XCTAssertTrue(chain.contains("version1"))
XCTAssertFalse(chain.contains("version2")) XCTAssertFalse(chain.contains("version2"))
@@ -62,8 +62,8 @@ final class MigrationChainTests: XCTestCase {
dynamic func test_ThatArrayMigrationChains_HaveLinearVersions() { dynamic func test_ThatArrayMigrationChains_HaveLinearVersions() {
let chain: MigrationChain = ["version1", "version2", "version3", "version4"] let chain: MigrationChain = ["version1", "version2", "version3", "version4"]
XCTAssertTrue(chain.valid) XCTAssertTrue(chain.isValid)
XCTAssertFalse(chain.empty) XCTAssertFalse(chain.isEmpty)
XCTAssertTrue(chain.contains("version1")) XCTAssertTrue(chain.contains("version1"))
XCTAssertTrue(chain.contains("version2")) XCTAssertTrue(chain.contains("version2"))
@@ -86,8 +86,8 @@ final class MigrationChainTests: XCTestCase {
"version2": "version3", "version2": "version3",
"version3": "version4" "version3": "version4"
] ]
XCTAssertTrue(chain.valid) XCTAssertTrue(chain.isValid)
XCTAssertFalse(chain.empty) XCTAssertFalse(chain.isEmpty)
XCTAssertTrue(chain.contains("version1")) XCTAssertTrue(chain.contains("version1"))
XCTAssertTrue(chain.contains("version2")) XCTAssertTrue(chain.contains("version2"))

View File

@@ -36,10 +36,13 @@ class SetupTests: BaseTestDataTestCase {
do { do {
let model = NSManagedObjectModel.mergedModel(from: [Bundle(for: type(of: self))])! let schemaHistory = SchemaHistory(
modelName: "Model",
let stack = DataStack(model: model, migrationChain: nil) bundle: Bundle(for: type(of: self)),
XCTAssertEqual(stack.coordinator.managedObjectModel, model) migrationChain: nil
)
let stack = DataStack(schemaHistory: schemaHistory)
XCTAssertEqual(stack.coordinator.managedObjectModel, schemaHistory.rawModel)
XCTAssertEqual(stack.rootSavingContext.persistentStoreCoordinator, stack.coordinator) XCTAssertEqual(stack.rootSavingContext.persistentStoreCoordinator, stack.coordinator)
XCTAssertNil(stack.rootSavingContext.parent) XCTAssertNil(stack.rootSavingContext.parent)
XCTAssertFalse(stack.rootSavingContext.isDataStackContext) XCTAssertFalse(stack.rootSavingContext.isDataStackContext)
@@ -47,18 +50,18 @@ class SetupTests: BaseTestDataTestCase {
XCTAssertEqual(stack.mainContext.parent, stack.rootSavingContext) XCTAssertEqual(stack.mainContext.parent, stack.rootSavingContext)
XCTAssertTrue(stack.mainContext.isDataStackContext) XCTAssertTrue(stack.mainContext.isDataStackContext)
XCTAssertFalse(stack.mainContext.isTransactionContext) XCTAssertFalse(stack.mainContext.isTransactionContext)
XCTAssertEqual(stack.model, model) XCTAssertEqual(stack.schemaHistory.rawModel, schemaHistory.rawModel)
XCTAssertTrue(stack.migrationChain.valid) XCTAssertTrue(stack.schemaHistory.migrationChain.isValid)
XCTAssertTrue(stack.migrationChain.empty) XCTAssertTrue(stack.schemaHistory.migrationChain.isEmpty)
XCTAssertTrue(stack.migrationChain.rootVersions.isEmpty) XCTAssertTrue(stack.schemaHistory.migrationChain.rootVersions.isEmpty)
XCTAssertTrue(stack.migrationChain.leafVersions.isEmpty) XCTAssertTrue(stack.schemaHistory.migrationChain.leafVersions.isEmpty)
CoreStore.defaultStack = stack CoreStore.defaultStack = stack
XCTAssertEqual(CoreStore.defaultStack, stack) XCTAssertEqual(CoreStore.defaultStack, stack)
} }
do { do {
let migrationChain: MigrationChain = ["version1", "version2", "version3"] let migrationChain: MigrationChain = ["version1", "version2", "version3", "Model"]
let stack = self.expectLogger([.logWarning]) { let stack = self.expectLogger([.logWarning]) {
@@ -69,7 +72,7 @@ class SetupTests: BaseTestDataTestCase {
) )
} }
XCTAssertEqual(stack.modelVersion, "Model") XCTAssertEqual(stack.modelVersion, "Model")
XCTAssertEqual(stack.migrationChain, migrationChain) XCTAssertEqual(stack.schemaHistory.migrationChain, migrationChain)
CoreStore.defaultStack = stack CoreStore.defaultStack = stack
XCTAssertEqual(CoreStore.defaultStack, stack) XCTAssertEqual(CoreStore.defaultStack, stack)
@@ -226,7 +229,10 @@ class SetupTests: BaseTestDataTestCase {
modelName: "Model", modelName: "Model",
bundle: Bundle(for: type(of: self)) bundle: Bundle(for: type(of: self))
) )
try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: stack.model[metadata]) try sqliteStore.eraseStorageAndWait(
metadata: metadata,
soureModelHint: stack.schemaHistory.schema(for: metadata)?.rawModel()
)
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path)) XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal"))) XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm"))) XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
@@ -344,7 +350,10 @@ class SetupTests: BaseTestDataTestCase {
modelName: "Model", modelName: "Model",
bundle: Bundle(for: type(of: self)) bundle: Bundle(for: type(of: self))
) )
try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: stack.model[metadata]) try sqliteStore.eraseStorageAndWait(
metadata: metadata,
soureModelHint: stack.schemaHistory.schema(for: metadata)?.rawModel()
)
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path)) XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal"))) XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm"))) XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))

View File

@@ -222,7 +222,7 @@ public enum CoreStoreError: Error, CustomNSError, Hashable {
internal init(_ error: Error?) { internal init(_ error: Error?) {
self = error.flatMap { $0.bridgeToSwift } ?? .unknown self = error.flatMap({ $0.bridgeToSwift }) ?? .unknown
} }
} }

View File

@@ -26,12 +26,12 @@
import Foundation import Foundation
// MARK: - XcdatamodelFilename // MARK: - XcodeDataModelFileName
/** /**
A `String` that pertains to the name of an *.xcdatamodeld file (without the file extension). A `String` that pertains to the name of an *.xcdatamodeld file (without the file extension).
*/ */
public typealias XcdatamodelFilename = String public typealias XcodeDataModelFileName = String
// MARK: - ModelConfiguration // MARK: - ModelConfiguration

View File

@@ -580,11 +580,11 @@ extension UUID: ImportableAttributeType {
enum Static { enum Static {
static let empty: UUID = { static let empty: UUID = cs_lazy {
var zero = Array<UInt8>(repeating: 0, count: 16) var zero = Array<UInt8>(repeating: 0, count: 16)
return NSUUID(uuidBytes: &zero) as UUID return NSUUID(uuidBytes: &zero) as UUID
}() }
} }
return Static.empty return Static.empty
} }

View File

@@ -0,0 +1,106 @@
//
// EntityIdentifier.swift
// CoreStore
//
// Copyright © 2017 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 CoreData
import Foundation
// MARK: - EntityIdentifier
internal struct EntityIdentifier: Hashable {
// MARK: - Category
internal enum Category: Int {
case coreData
case coreStore
}
// MARK: -
internal let category: Category
internal let interfacedClassName: String
internal init(_ type: NSManagedObject.Type) {
self.category = .coreData
self.interfacedClassName = String(reflecting: type)
}
internal init(_ type: CoreStoreObject.Type) {
self.category = .coreStore
self.interfacedClassName = String(reflecting: type)
}
internal init(_ type: DynamicObject.Type) {
switch type {
case let type as NSManagedObject.Type:
self.init(type)
case let type as CoreStoreObject.Type:
self.init(type)
default:
CoreStore.abort("\(cs_typeName(DynamicObject.self)) is not meant to be implemented by external types.")
}
}
internal init(_ entityDescription: NSEntityDescription) {
if let anyEntity = entityDescription.anyEntity {
self.category = .coreStore
self.interfacedClassName = NSStringFromClass(anyEntity.type)
}
else {
self.category = .coreData
self.interfacedClassName = entityDescription.managedObjectClassName!
}
}
// MARK: Equatable
static func == (lhs: EntityIdentifier, rhs: EntityIdentifier) -> Bool {
return lhs.category == rhs.category
&& lhs.interfacedClassName == rhs.interfacedClassName
}
// MARK: Hashable
var hashValue: Int {
return self.category.hashValue
^ self.interfacedClassName.hashValue
}
}

View File

@@ -100,3 +100,12 @@ internal func cs_typeName(_ name: String?) -> String {
return "<\(name ?? "unknown")>" return "<\(name ?? "unknown")>"
} }
// MARK: Functional
@inline(__always)
internal func cs_lazy<T>(_ closure: () -> T) -> T {
return closure()
}

View File

@@ -0,0 +1,76 @@
//
// NSEntityDescription+DynamicModel.swift
// CoreStore
//
// Copyright © 2017 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 CoreData
import Foundation
// MARK: - NSEntityDescription
internal extension NSEntityDescription {
@nonobjc
internal var anyEntity: CoreStoreSchema.AnyEntity? {
get {
guard let userInfo = self.userInfo,
let typeName = userInfo[UserInfoKey.CoreStoreManagedObjectTypeName] as! String?,
let entityName = userInfo[UserInfoKey.CoreStoreManagedObjectEntityName] as! String? else {
return nil
}
return CoreStoreSchema.AnyEntity(
type: NSClassFromString(typeName) as! CoreStoreObject.Type,
entityName: entityName
)
}
set {
if let newValue = newValue {
self.userInfo = [
UserInfoKey.CoreStoreManagedObjectTypeName: NSStringFromClass(newValue.type),
UserInfoKey.CoreStoreManagedObjectEntityName: newValue.entityName
]
}
else {
self.userInfo = [:]
}
}
}
// MARK: Private
// MARK: - UserInfoKey
fileprivate enum UserInfoKey {
fileprivate static let CoreStoreManagedObjectTypeName = "CoreStoreManagedObjectTypeName"
fileprivate static let CoreStoreManagedObjectEntityName = "CoreStoreManagedObjectEntityName"
}
}

View File

@@ -1,274 +0,0 @@
//
// NSManagedObjectModel+Setup.swift
// CoreStore
//
// Copyright © 2015 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import Foundation
import CoreData
// MARK: - NSManagedObjectModel
internal extension NSManagedObjectModel {
// MARK: Internal
@nonobjc
internal static func fromBundle(_ bundle: Bundle, modelName: String, modelVersionHints: Set<String> = []) -> NSManagedObjectModel {
guard let modelFilePath = bundle.path(forResource: modelName, ofType: "momd") else {
// For users migrating from very old Xcode versions: Old xcdatamodel files are not contained inside xcdatamodeld (with a "d"), and will thus fail this check. If that was the case, create a new xcdatamodeld file and copy all contents into the new model.
let foundModels = bundle
.paths(forResourcesOfType: "momd", inDirectory: nil)
.map({ ($0 as NSString).lastPathComponent })
CoreStore.abort("Could not find \"\(modelName).momd\" from the bundle \"\(bundle.bundleIdentifier ?? "<nil>")\". Other model files in bundle: \(foundModels.coreStoreDumpString)")
}
let modelFileURL = URL(fileURLWithPath: modelFilePath)
let versionInfoPlistURL = modelFileURL.appendingPathComponent("VersionInfo.plist", isDirectory: false)
guard let versionInfo = NSDictionary(contentsOf: versionInfoPlistURL),
let versionHashes = versionInfo["NSManagedObjectModel_VersionHashes"] as? [String: AnyObject] else {
CoreStore.abort("Could not load \(cs_typeName(NSManagedObjectModel.self)) metadata from path \"\(versionInfoPlistURL)\".")
}
let modelVersions = Set(versionHashes.keys)
let currentModelVersion: String
if let plistModelVersion = versionInfo["NSManagedObjectModel_CurrentVersionName"] as? String,
modelVersionHints.isEmpty || modelVersionHints.contains(plistModelVersion) {
currentModelVersion = plistModelVersion
}
else if let resolvedVersion = modelVersions.intersection(modelVersionHints).first {
CoreStore.log(
.warning,
message: "The MigrationChain leaf versions do not include the model file's current version. Resolving to version \"\(resolvedVersion)\"."
)
currentModelVersion = resolvedVersion
}
else if let resolvedVersion = modelVersions.first ?? modelVersionHints.first {
if !modelVersionHints.isEmpty {
CoreStore.log(
.warning,
message: "The MigrationChain leaf versions do not include any of the model file's embedded versions. Resolving to version \"\(resolvedVersion)\"."
)
}
currentModelVersion = resolvedVersion
}
else {
CoreStore.abort("No model files were found in URL \"\(modelFileURL)\".")
}
var modelVersionFileURL: URL?
for modelVersion in modelVersions {
let fileURL = modelFileURL.appendingPathComponent("\(modelVersion).mom", isDirectory: false)
if modelVersion == currentModelVersion {
modelVersionFileURL = fileURL
continue
}
precondition(
NSManagedObjectModel(contentsOf: fileURL) != nil,
"Could not find the \"\(modelVersion).mom\" version file for the model at URL \"\(modelFileURL)\"."
)
}
if let modelVersionFileURL = modelVersionFileURL,
let rootModel = NSManagedObjectModel(contentsOf: modelVersionFileURL) {
// TODO: apply to DynamicModel as well
rootModel.modelVersionFileURL = modelVersionFileURL
rootModel.modelVersions = modelVersions
rootModel.currentModelVersion = currentModelVersion
return rootModel
}
CoreStore.abort("Could not create an \(cs_typeName(NSManagedObjectModel.self)) from the model at URL \"\(modelFileURL)\".")
}
@nonobjc
internal private(set) var currentModelVersion: String? {
get {
let value: NSString? = cs_getAssociatedObjectForKey(
&PropertyKeys.currentModelVersion,
inObject: self
)
return value as String?
}
set {
cs_setAssociatedCopiedObject(
newValue == nil ? nil : (newValue! as NSString),
forKey: &PropertyKeys.currentModelVersion,
inObject: self
)
}
}
@nonobjc
internal private(set) var modelVersions: Set<String>? {
get {
let value: NSSet? = cs_getAssociatedObjectForKey(
&PropertyKeys.modelVersions,
inObject: self
)
return value as? Set<String>
}
set {
cs_setAssociatedCopiedObject(
newValue == nil ? nil : (newValue! as NSSet),
forKey: &PropertyKeys.modelVersions,
inObject: self
)
}
}
@nonobjc
internal var entityDescriptionsByEntityIdentifier: [EntityIdentifier: NSEntityDescription] {
if let mapping: NSDictionary = cs_getAssociatedObjectForKey(&PropertyKeys.objectClassNamesByEntityName, inObject: self) {
return mapping as! [EntityIdentifier: NSEntityDescription]
}
var mapping: [EntityIdentifier: NSEntityDescription] = [:]
self.entities.forEach { (entityDescription) in
let entityIdentifier = EntityIdentifier(entityDescription)
mapping[entityIdentifier] = entityDescription
}
cs_setAssociatedCopiedObject(
mapping as NSDictionary,
forKey: &PropertyKeys.objectClassNamesByEntityName,
inObject: self
)
return mapping
}
@nonobjc
internal func mergedModels() -> [NSManagedObjectModel] {
return self.modelVersions?.map { self[$0] }.flatMap { $0 == nil ? [] : [$0!] } ?? [self]
}
@nonobjc
internal subscript(modelVersion: String) -> NSManagedObjectModel? {
if modelVersion == self.currentModelVersion {
return self
}
guard let modelFileURL = self.modelFileURL,
let modelVersions = self.modelVersions,
modelVersions.contains(modelVersion) else {
return nil
}
// TODO: apply to DynamicModel as well
let versionModelFileURL = modelFileURL.appendingPathComponent("\(modelVersion).mom", isDirectory: false)
guard let model = NSManagedObjectModel(contentsOf: versionModelFileURL) else {
return nil
}
model.currentModelVersion = modelVersion
model.modelVersionFileURL = versionModelFileURL
model.modelVersions = modelVersions
return model
}
@nonobjc
internal subscript(metadata: [String: Any]) -> NSManagedObjectModel? {
guard let modelHashes = metadata[NSStoreModelVersionHashesKey] as? [String : Data] else {
return nil
}
for modelVersion in self.modelVersions ?? [] {
if let versionModel = self[modelVersion], modelHashes == versionModel.entityVersionHashesByName {
return versionModel
}
}
return nil
}
// MARK: Private
@nonobjc
private var modelFileURL: URL? {
get {
return self.modelVersionFileURL?.deletingLastPathComponent()
}
}
@nonobjc
private var modelVersionFileURL: URL? {
get {
let value: NSURL? = cs_getAssociatedObjectForKey(
&PropertyKeys.modelVersionFileURL,
inObject: self
)
return value as URL?
}
set {
cs_setAssociatedCopiedObject(
newValue as NSURL?,
forKey: &PropertyKeys.modelVersionFileURL,
inObject: self
)
}
}
private struct PropertyKeys {
static var objectClassNamesByEntityName: Void?
static var modelVersionFileURL: Void?
static var modelVersions: Void?
static var currentModelVersion: Void?
}
}

View File

@@ -158,6 +158,32 @@ extension CoreStoreError: CustomDebugStringConvertible, CoreStoreDebugStringConv
} }
// MARK: - CoreStoreSchema
extension CoreStoreSchema: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
return createFormattedString(
"(", ")",
("modelVersion", self.modelVersion),
("entitiesByConfiguration", self.entitiesByConfiguration),
("rawModel", self.rawModel())
)
}
}
// MARK: - DataStack // MARK: - DataStack
extension DataStack: CustomDebugStringConvertible, CoreStoreDebugStringConvertible { extension DataStack: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
@@ -179,14 +205,38 @@ extension DataStack: CustomDebugStringConvertible, CoreStoreDebugStringConvertib
("coordinator", self.coordinator), ("coordinator", self.coordinator),
("rootSavingContext", self.rootSavingContext), ("rootSavingContext", self.rootSavingContext),
("mainContext", self.mainContext), ("mainContext", self.mainContext),
("model", self.model), ("schemaHistory", self.schemaHistory),
("migrationChain", self.migrationChain),
("coordinator.persistentStores", self.coordinator.persistentStores) ("coordinator.persistentStores", self.coordinator.persistentStores)
) )
} }
} }
// MARK: - Entity
extension Entity: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
return createFormattedString(
"(", ")",
("type", self.type),
("entityName", self.entityName)
)
}
}
// MARK: - From // MARK: - From
extension From: CustomDebugStringConvertible, CoreStoreDebugStringConvertible { extension From: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
@@ -350,6 +400,31 @@ extension LegacySQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringC
} }
// MARK: - LegacyXcodeDataModel
extension LegacyXcodeDataModel: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
return createFormattedString(
"(", ")",
("modelVersion", self.modelVersion),
("rawModel", self.rawModel())
)
}
}
// MARK: - ListMonitor // MARK: - ListMonitor
@available(OSX 10.12, *) @available(OSX 10.12, *)
@@ -456,7 +531,7 @@ extension MigrationChain: CustomDebugStringConvertible, CoreStoreDebugStringConv
public var coreStoreDumpString: String { public var coreStoreDumpString: String {
guard self.valid else { guard self.isValid else {
return "<invalid migration chain>" return "<invalid migration chain>"
} }
@@ -669,6 +744,32 @@ extension SectionBy: CustomDebugStringConvertible, CoreStoreDebugStringConvertib
} }
// MARK: - SchemaHistory
extension SchemaHistory: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
return createFormattedString(
"(", ")",
("currentModelVersion", self.currentModelVersion),
("migrationChain", self.migrationChain),
("schemaByVersion", self.schemaByVersion)
)
}
}
// MARK: - Select // MARK: - Select
extension Select: CustomDebugStringConvertible, CoreStoreDebugStringConvertible { extension Select: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
@@ -896,6 +997,32 @@ extension Where: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
} }
// MARK: - XcodeDataModel
extension XcodeDataModel: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
return createFormattedString(
"(", ")",
("modelVersion", self.modelVersion),
("modelVersionFileURL", self.modelVersionFileURL),
("rawModel", self.rawModel())
)
}
}
// MARK: - Private: Utilities // MARK: - Private: Utilities
private typealias DumpInfo = [(key: String, value: Any)] private typealias DumpInfo = [(key: String, value: Any)]
@@ -972,7 +1099,7 @@ public protocol CoreStoreDebugStringConvertible {
} }
// MARK: - Private: // MARK: - Standard Types:
extension Array: CoreStoreDebugStringConvertible { extension Array: CoreStoreDebugStringConvertible {
@@ -1214,7 +1341,15 @@ extension NSSortDescriptor: CoreStoreDebugStringConvertible {
} }
} }
extension URL: CoreStoreDebugStringConvertible { extension NSString: CoreStoreDebugStringConvertible {
public var coreStoreDumpString: String {
return "\"\(self)\""
}
}
extension NSURL: CoreStoreDebugStringConvertible {
public var coreStoreDumpString: String { public var coreStoreDumpString: String {
@@ -1249,3 +1384,11 @@ extension String: CoreStoreDebugStringConvertible {
return "\"\(self)\"" return "\"\(self)\""
} }
} }
extension URL: CoreStoreDebugStringConvertible {
public var coreStoreDumpString: String {
return "\"\(self)\""
}
}

View File

@@ -218,7 +218,7 @@ public extension DataStack {
try storage.eraseStorageAndWait( try storage.eraseStorageAndWait(
metadata: metadata, metadata: metadata,
soureModelHint: self.model[metadata] soureModelHint: self.schemaHistory.schema(for: metadata)?.rawModel()
) )
_ = try self.addStorageAndWait(storage) _ = try self.addStorageAndWait(storage)
@@ -382,7 +382,9 @@ public extension DataStack {
at: cacheFileURL, at: cacheFileURL,
options: storeOptions options: storeOptions
) )
_ = try self.model[metadata].flatMap(storage.eraseStorageAndWait) _ = try self.schemaHistory
.schema(for: metadata)
.flatMap({ try storage.eraseStorageAndWait(soureModel: $0.rawModel()) })
_ = try self.createPersistentStoreFromStorage( _ = try self.createPersistentStoreFromStorage(
storage, storage,
finalURL: cacheFileURL, finalURL: cacheFileURL,
@@ -497,7 +499,7 @@ public extension DataStack {
let error = CoreStoreError.mappingModelNotFound( let error = CoreStoreError.mappingModelNotFound(
localStoreURL: fileURL, localStoreURL: fileURL,
targetModel: self.model, targetModel: self.schemaHistory.rawModel,
targetModelVersion: self.modelVersion targetModelVersion: self.modelVersion
) )
CoreStore.log( CoreStore.log(
@@ -545,12 +547,12 @@ public extension DataStack {
let error = CoreStoreError.mappingModelNotFound( let error = CoreStoreError.mappingModelNotFound(
localStoreURL: storage.fileURL, localStoreURL: storage.fileURL,
targetModel: self.model, targetModel: self.schemaHistory.rawModel,
targetModelVersion: self.modelVersion targetModelVersion: self.modelVersion
) )
CoreStore.log( CoreStore.log(
error, error,
"Failed to find migration steps from \(cs_typeName(storage)) at URL \"\(storage.fileURL)\" to version model \"\(self.model)\"." "Failed to find migration steps from \(cs_typeName(storage)) at URL \"\(storage.fileURL)\" to version model \"\(self.schemaHistory.rawModel)\"."
) )
DispatchQueue.main.async { DispatchQueue.main.async {
@@ -592,7 +594,7 @@ public extension DataStack {
let progress = Progress(parent: nil, userInfo: nil) let progress = Progress(parent: nil, userInfo: nil)
progress.totalUnitCount = numberOfMigrations progress.totalUnitCount = numberOfMigrations
for (sourceModel, destinationModel, mappingModel, _) in migrationSteps { for (sourceModel, destinationModel, mappingModel, migrationType) in migrationSteps {
progress.becomeCurrent(withPendingUnitCount: 1) progress.becomeCurrent(withPendingUnitCount: 1)
@@ -620,8 +622,13 @@ public extension DataStack {
) )
} }
catch { catch {
migrationResult = MigrationResult(error) let migrationError = CoreStoreError(error)
CoreStore.log(
migrationError,
"Failed to migrate version model \"\(migrationType.sourceVersion)\" to version \"\(migrationType.destinationVersion)\"."
)
migrationResult = MigrationResult(migrationError)
cancelled = true cancelled = true
} }
} }
@@ -658,28 +665,27 @@ public extension DataStack {
private func computeMigrationFromStorage<T: LocalStorage>(_ storage: T, metadata: [String: Any]) -> [(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType)]? { private func computeMigrationFromStorage<T: LocalStorage>(_ storage: T, metadata: [String: Any]) -> [(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType)]? {
let model = self.model let schemaHistory = self.schemaHistory
if model.isConfiguration(withName: storage.configuration, compatibleWithStoreMetadata: metadata) { if schemaHistory.rawModel.isConfiguration(withName: storage.configuration, compatibleWithStoreMetadata: metadata) {
return [] return []
} }
guard let initialModel = model[metadata], guard let initialSchema = schemaHistory.schema(for: metadata) else {
var currentVersion = initialModel.currentModelVersion else {
return nil
return nil
} }
var currentVersion = initialSchema.modelVersion
let migrationChain: MigrationChain = self.migrationChain.empty let migrationChain: MigrationChain = schemaHistory.migrationChain.isEmpty
? [currentVersion: model.currentModelVersion!] ? [currentVersion: schemaHistory.currentModelVersion]
: self.migrationChain : schemaHistory.migrationChain
var migrationSteps = [(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType)]() var migrationSteps = [(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType)]()
while let nextVersion = migrationChain.nextVersionFrom(currentVersion), while let nextVersion = migrationChain.nextVersionFrom(currentVersion),
let sourceModel = model[currentVersion], let sourceModel = schemaHistory.rawModel(for: currentVersion),
sourceModel != model, sourceModel != schemaHistory.rawModel,
let destinationModel = model[nextVersion] { let destinationModel = schemaHistory.rawModel(for: nextVersion) {
if let mappingModel = NSMappingModel( if let mappingModel = NSMappingModel(
from: storage.mappingModelBundles, from: storage.mappingModelBundles,
@@ -727,7 +733,7 @@ public extension DataStack {
currentVersion = nextVersion currentVersion = nextVersion
} }
if migrationSteps.last?.destinationModel == model { if migrationSteps.last?.destinationModel == schemaHistory.rawModel {
return migrationSteps return migrationSteps
} }
@@ -775,21 +781,8 @@ public extension DataStack {
} }
catch { catch {
do { _ = try? fileManager.removeItem(at: temporaryFileURL)
throw CoreStoreError(error)
try fileManager.removeItem(at: temporaryFileURL)
}
catch _ { }
let sourceVersion = migrationManager.sourceModel.currentModelVersion ?? "???"
let destinationVersion = migrationManager.destinationModel.currentModelVersion ?? "???"
let migrationError = CoreStoreError(error)
CoreStore.log(
migrationError,
"Failed to migrate from version model \"\(sourceVersion)\" to version model \"\(destinationVersion)\"."
)
throw migrationError
} }
do { do {
@@ -806,21 +799,8 @@ public extension DataStack {
} }
catch { catch {
do { _ = try? fileManager.removeItem(at: temporaryFileURL)
throw CoreStoreError(error)
try fileManager.removeItem(at: temporaryFileURL)
}
catch _ { }
let sourceVersion = migrationManager.sourceModel.currentModelVersion ?? "???"
let destinationVersion = migrationManager.destinationModel.currentModelVersion ?? "???"
let fileError = CoreStoreError(error)
CoreStore.log(
fileError,
"Failed to save store after migrating from version model \"\(sourceVersion)\" to version model \"\(destinationVersion)\"."
)
throw fileError
} }
} }
} }

View File

@@ -70,7 +70,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
self.versionTree = [:] self.versionTree = [:]
self.rootVersions = [] self.rootVersions = []
self.leafVersions = [] self.leafVersions = []
self.valid = true self.isValid = true
} }
/** /**
@@ -81,7 +81,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
self.versionTree = [:] self.versionTree = [:]
self.rootVersions = [value] self.rootVersions = [value]
self.leafVersions = [value] self.leafVersions = [value]
self.valid = true self.isValid = true
} }
/** /**
@@ -93,13 +93,13 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
var lastVersion: String? var lastVersion: String?
var versionTree = [String: String]() var versionTree = [String: String]()
var valid = true var isValid = true
for version in elements { for version in elements {
if let lastVersion = lastVersion, if let lastVersion = lastVersion,
let _ = versionTree.updateValue(version, forKey: lastVersion) { let _ = versionTree.updateValue(version, forKey: lastVersion) {
valid = false isValid = false
} }
lastVersion = version lastVersion = version
} }
@@ -107,7 +107,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
self.versionTree = versionTree self.versionTree = versionTree
self.rootVersions = Set(elements.prefix(1)) self.rootVersions = Set(elements.prefix(1))
self.leafVersions = Set(elements.suffix(1)) self.leafVersions = Set(elements.suffix(1))
self.valid = valid self.isValid = isValid
} }
/** /**
@@ -115,7 +115,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
*/ */
public init(_ elements: [(String, String)]) { public init(_ elements: [(String, String)]) {
var valid = true var isValid = true
var versionTree = [String: String]() var versionTree = [String: String]()
elements.forEach { (sourceVersion, destinationVersion) in elements.forEach { (sourceVersion, destinationVersion) in
@@ -126,7 +126,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
CoreStore.assert(false, "\(cs_typeName(MigrationChain.self))'s migration chain could not be created due to ambiguous version paths.") CoreStore.assert(false, "\(cs_typeName(MigrationChain.self))'s migration chain could not be created due to ambiguous version paths.")
valid = false isValid = false
} }
let leafVersions = Set( let leafVersions = Set(
elements elements
@@ -156,7 +156,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
self.versionTree = versionTree self.versionTree = versionTree
self.rootVersions = Set(versionTree.keys).subtracting(versionTree.values) self.rootVersions = Set(versionTree.keys).subtracting(versionTree.values)
self.leafVersions = leafVersions self.leafVersions = leafVersions
self.valid = valid && Set(versionTree.keys).union(versionTree.values).filter { isVersionAmbiguous($0) }.count <= 0 self.isValid = isValid && Set(versionTree.keys).union(versionTree.values).filter { isVersionAmbiguous($0) }.count <= 0
} }
/** /**
@@ -223,7 +223,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
return lhs.versionTree == rhs.versionTree return lhs.versionTree == rhs.versionTree
&& lhs.rootVersions == rhs.rootVersions && lhs.rootVersions == rhs.rootVersions
&& lhs.leafVersions == rhs.leafVersions && lhs.leafVersions == rhs.leafVersions
&& lhs.valid == rhs.valid && lhs.isValid == rhs.isValid
} }
@@ -231,9 +231,9 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
internal let rootVersions: Set<String> internal let rootVersions: Set<String>
internal let leafVersions: Set<String> internal let leafVersions: Set<String>
internal let valid: Bool internal let isValid: Bool
internal var empty: Bool { internal var isEmpty: Bool {
return self.versionTree.count <= 0 return self.versionTree.count <= 0
} }

View File

@@ -54,7 +54,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
- parameter versionChain: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack. - parameter versionChain: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/ */
@objc @objc
public convenience init(modelName: XcdatamodelFilename?, bundle: Bundle?, versionChain: [String]?) { public convenience init(modelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
self.init( self.init(
DataStack( DataStack(
@@ -73,7 +73,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
- parameter versionTree: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack. - parameter versionTree: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/ */
@objc @objc
public convenience init(modelName: XcdatamodelFilename?, bundle: Bundle?, versionTree: [String: String]?) { public convenience init(modelName: XcodeDataModelFileName?, bundle: Bundle?, versionTree: [String: String]?) {
self.init( self.init(
DataStack( DataStack(
@@ -84,40 +84,6 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
) )
} }
/**
Initializes a `DataStack` from an `NSManagedObjectModel`.
- parameter model: the `NSManagedObjectModel` for the stack
- parameter versionChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/
@objc
public convenience init(model: NSManagedObjectModel, versionChain: [String]?) {
self.init(
DataStack(
model: model,
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
)
)
}
/**
Initializes a `DataStack` from an `NSManagedObjectModel`.
- parameter model: the `NSManagedObjectModel` for the stack
- parameter versionTree: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/
@objc
public convenience init(model: NSManagedObjectModel, versionTree: [String]?) {
self.init(
DataStack(
model: model,
migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
)
)
}
/** /**
Returns the stack's model version. The version string is the same as the name of the version-specific .xcdatamodeld file. Returns the stack's model version. The version string is the same as the name of the version-specific .xcdatamodeld file.
*/ */
@@ -261,6 +227,42 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
// MARK: Deprecated // MARK: Deprecated
/**
Initializes a `DataStack` from an `NSManagedObjectModel`.
- parameter model: the `NSManagedObjectModel` for the stack
- parameter versionChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/
@available(*, deprecated: 3.1, message: "Use the -[initWithModelName:bundle:versionChain:] initializer.")
@objc
public convenience init(model: NSManagedObjectModel, versionChain: [String]?) {
self.init(
DataStack(
model: model,
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
)
)
}
/**
Initializes a `DataStack` from an `NSManagedObjectModel`.
- parameter model: the `NSManagedObjectModel` for the stack
- parameter versionTree: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/
@available(*, deprecated: 3.1, message: "Use the -[initWithModelName:bundle:versionTree:] initializer.")
@objc
public convenience init(model: NSManagedObjectModel, versionTree: [String]?) {
self.init(
DataStack(
model: model,
migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
)
)
}
/** /**
Returns the entity name-to-class type mapping from the stack's model. Returns the entity name-to-class type mapping from the stack's model.
*/ */

View File

@@ -41,30 +41,24 @@ public final class DataStack: Equatable {
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used. - parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
- parameter migrationChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack. - parameter migrationChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/ */
public convenience init(modelName: XcdatamodelFilename = DataStack.applicationName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) { public convenience init(modelName: XcodeDataModelFileName = DataStack.applicationName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) {
let model = NSManagedObjectModel.fromBundle(
bundle,
modelName: modelName,
modelVersionHints: migrationChain.leafVersions
)
self.init(model: model, migrationChain: migrationChain)
}
public convenience init(dynamicModel: DynamicModel) {
self.init(model: dynamicModel.createModel())
}
public convenience init(dynamicModels: [DynamicModel], migrationChain: MigrationChain = nil) {
CoreStore.assert(
migrationChain.valid,
"Invalid migration chain passed to the \(cs_typeName(DataStack.self)). Check that the model versions' order is correct and that no repetitions or ambiguities exist."
)
self.init( self.init(
model: NSManagedObjectModel(byMerging: dynamicModels.map({ $0.createModel() }))!, schemaHistory: SchemaHistory(
migrationChain: migrationChain modelName: modelName,
bundle: bundle,
migrationChain: migrationChain
)
)
}
public convenience init(_ schema: DynamicSchema, _ otherSchema: DynamicSchema..., migrationChain: MigrationChain = nil) {
self.init(
schemaHistory: SchemaHistory(
allSchema: [schema] + otherSchema,
migrationChain: migrationChain
)
) )
} }
@@ -74,21 +68,20 @@ public final class DataStack: Equatable {
- parameter model: the `NSManagedObjectModel` for the stack - parameter model: the `NSManagedObjectModel` for the stack
- parameter migrationChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack. - parameter migrationChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/ */
public required init(model: NSManagedObjectModel, migrationChain: MigrationChain = nil) { public required init(schemaHistory: SchemaHistory) {
// TODO: test before release (rolled back) // TODO: test before release (rolled back)
// _ = DataStack.isGloballyInitialized // _ = DataStack.isGloballyInitialized
CoreStore.assert( CoreStore.assert(
migrationChain.valid, schemaHistory.migrationChain.isValid,
"Invalid migration chain passed to the \(cs_typeName(DataStack.self)). Check that the model versions' order is correct and that no repetitions or ambiguities exist." "Invalid migration chain passed to the \(cs_typeName(DataStack.self)). Check that the model versions' order is correct and that no repetitions or ambiguities exist."
) )
self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: model) self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: schemaHistory.rawModel)
self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator) self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator)
self.mainContext = NSManagedObjectContext.mainContextForRootContext(self.rootSavingContext) self.mainContext = NSManagedObjectContext.mainContextForRootContext(self.rootSavingContext)
self.model = model self.schemaHistory = schemaHistory
self.migrationChain = migrationChain
self.rootSavingContext.parentStack = self self.rootSavingContext.parentStack = self
@@ -100,7 +93,7 @@ public final class DataStack: Equatable {
*/ */
public var modelVersion: String { public var modelVersion: String {
return self.model.currentModelVersion! return self.schemaHistory.currentModelVersion
} }
/** /**
@@ -109,7 +102,7 @@ public final class DataStack: Equatable {
public func entityTypesByName(for type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] { public func entityTypesByName(for type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
var entityTypesByName: [EntityName: NSManagedObject.Type] = [:] var entityTypesByName: [EntityName: NSManagedObject.Type] = [:]
for (entityIdentifier, entityDescription) in self.model.entityDescriptionsByEntityIdentifier { for (entityIdentifier, entityDescription) in self.schemaHistory.entityDescriptionsByEntityIdentifier {
switch entityIdentifier.category { switch entityIdentifier.category {
@@ -133,7 +126,7 @@ public final class DataStack: Equatable {
public func entityTypesByName(for type: CoreStoreObject.Type) -> [EntityName: CoreStoreObject.Type] { public func entityTypesByName(for type: CoreStoreObject.Type) -> [EntityName: CoreStoreObject.Type] {
var entityTypesByName: [EntityName: CoreStoreObject.Type] = [:] var entityTypesByName: [EntityName: CoreStoreObject.Type] = [:]
for (entityIdentifier, entityDescription) in self.model.entityDescriptionsByEntityIdentifier { for (entityIdentifier, entityDescription) in self.schemaHistory.entityDescriptionsByEntityIdentifier {
switch entityIdentifier.category { switch entityIdentifier.category {
@@ -332,7 +325,7 @@ public final class DataStack: Equatable {
) )
try storage.eraseStorageAndWait( try storage.eraseStorageAndWait(
metadata: metadata, metadata: metadata,
soureModelHint: self.model[metadata] soureModelHint: self.schemaHistory.schema(for: metadata)?.rawModel()
) )
let finalStoreOptions = storage.dictionary(forOptions: storage.localStorageOptions) let finalStoreOptions = storage.dictionary(forOptions: storage.localStorageOptions)
_ = try self.createPersistentStoreFromStorage( _ = try self.createPersistentStoreFromStorage(
@@ -425,7 +418,9 @@ public final class DataStack: Equatable {
at: cacheFileURL, at: cacheFileURL,
options: storeOptions options: storeOptions
) )
_ = try self.model[metadata].flatMap(storage.eraseStorageAndWait) _ = try self.schemaHistory
.schema(for: metadata)
.flatMap({ try storage.eraseStorageAndWait(soureModel: $0.rawModel()) })
_ = try self.createPersistentStoreFromStorage( _ = try self.createPersistentStoreFromStorage(
storage, storage,
finalURL: cacheFileURL, finalURL: cacheFileURL,
@@ -464,11 +459,10 @@ public final class DataStack: Equatable {
internal let coordinator: NSPersistentStoreCoordinator internal let coordinator: NSPersistentStoreCoordinator
internal let rootSavingContext: NSManagedObjectContext internal let rootSavingContext: NSManagedObjectContext
internal let mainContext: NSManagedObjectContext internal let mainContext: NSManagedObjectContext
internal let model: NSManagedObjectModel internal let schemaHistory: SchemaHistory
internal let migrationChain: MigrationChain
internal let childTransactionQueue = DispatchQueue.serial("com.coreStore.dataStack.childTransactionQueue") internal let childTransactionQueue = DispatchQueue.serial("com.coreStore.dataStack.childTransactionQueue")
internal let storeMetadataUpdateQueue = DispatchQueue.concurrent("com.coreStore.persistentStoreBarrierQueue") internal let storeMetadataUpdateQueue = DispatchQueue.concurrent("com.coreStore.persistentStoreBarrierQueue")
internal let migrationQueue: OperationQueue = { internal let migrationQueue: OperationQueue = cs_lazy {
let migrationQueue = OperationQueue() let migrationQueue = OperationQueue()
migrationQueue.maxConcurrentOperationCount = 1 migrationQueue.maxConcurrentOperationCount = 1
@@ -476,7 +470,7 @@ public final class DataStack: Equatable {
migrationQueue.qualityOfService = .utility migrationQueue.qualityOfService = .utility
migrationQueue.underlyingQueue = DispatchQueue.serial("com.coreStore.migrationQueue", qos: .userInitiated) migrationQueue.underlyingQueue = DispatchQueue.serial("com.coreStore.migrationQueue", qos: .userInitiated)
return migrationQueue return migrationQueue
}() }
internal func persistentStoreForStorage(_ storage: StorageInterface) -> NSPersistentStore? { internal func persistentStoreForStorage(_ storage: StorageInterface) -> NSPersistentStore? {
@@ -562,7 +556,7 @@ public final class DataStack: Equatable {
internal func entityDescription(for entityIdentifier: EntityIdentifier) -> NSEntityDescription? { internal func entityDescription(for entityIdentifier: EntityIdentifier) -> NSEntityDescription? {
return self.model.entityDescriptionsByEntityIdentifier[entityIdentifier] return self.schemaHistory.entityDescriptionsByEntityIdentifier[entityIdentifier]
} }
@@ -596,6 +590,30 @@ public final class DataStack: Equatable {
// MARK: Deprecated // MARK: Deprecated
/**
Initializes a `DataStack` from an `NSManagedObjectModel`.
- parameter model: the `NSManagedObjectModel` for the stack
- parameter migrationChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/
@available(*, deprecated: 3.1, message: "Use the new DataStack.init(schemaHistory:) initializer passing a LegacyXcodeDataModel instance as argument")
public convenience init(model: NSManagedObjectModel, migrationChain: MigrationChain = nil) {
let modelVersion = migrationChain.leafVersions.first!
self.init(
schemaHistory: SchemaHistory(
allSchema: [
LegacyXcodeDataModel(
modelName: modelVersion,
model: model
)
],
migrationChain: migrationChain,
exactCurrentModelVersion: modelVersion
)
)
}
/** /**
Returns the entity name-to-class type mapping from the `DataStack`'s model. Returns the entity name-to-class type mapping from the `DataStack`'s model.
*/ */

View File

@@ -1,5 +1,5 @@
// //
// DynamicModel.swift // CoreStoreSchema.swift
// CoreStore // CoreStore
// //
// Copyright © 2017 John Rommel Estropia // Copyright © 2017 John Rommel Estropia
@@ -23,20 +23,31 @@
// SOFTWARE. // SOFTWARE.
// //
import CoreGraphics import CoreData
import Foundation import Foundation
// MARK: - DynamicModel // MARK: - CoreStoreSchema
public final class DynamicModel { public final class CoreStoreSchema: DynamicSchema {
public convenience init(version: String, entities: [EntityProtocol]) { public convenience init(modelVersion: String, _ entity: DynamicEntity, _ entities: DynamicEntity...) {
self.init(version: version, entitiesByConfiguration: [DataStack.defaultConfigurationName: entities]) self.init(
modelVersion: modelVersion,
entities: [entity] + entities
)
} }
public required init(version: String, entitiesByConfiguration: [String: [EntityProtocol]]) { public convenience init(modelVersion: String, entities: [DynamicEntity]) {
self.init(
modelVersion: modelVersion,
entitiesByConfiguration: [DataStack.defaultConfigurationName: entities]
)
}
public required init(modelVersion: String, entitiesByConfiguration: [String: [DynamicEntity]]) {
var actualEntitiesByConfiguration: [String: Set<AnyEntity>] = [:] var actualEntitiesByConfiguration: [String: Set<AnyEntity>] = [:]
for (configuration, entities) in entitiesByConfiguration { for (configuration, entities) in entitiesByConfiguration {
@@ -56,19 +67,57 @@ public final class DynamicModel {
"Ambiguous entity types or entity names were found in the model. Ensure that the entity types and entity names are unique to each other. Entities: \(allEntities)" "Ambiguous entity types or entity names were found in the model. Ensure that the entity types and entity names are unique to each other. Entities: \(allEntities)"
) )
self.version = version self.modelVersion = modelVersion
self.entitiesByConfiguration = actualEntitiesByConfiguration self.entitiesByConfiguration = actualEntitiesByConfiguration
self.allEntities = allEntities self.allEntities = allEntities
} }
// MARK: - DynamicSchema
public let modelVersion: ModelVersion
public func rawModel() -> NSManagedObjectModel {
if let cachedRawModel = self.cachedRawModel {
return cachedRawModel
}
let rawModel = NSManagedObjectModel()
var entityDescriptionsByEntity: [AnyEntity: NSEntityDescription] = [:]
for entity in self.allEntities {
let entityDescription = self.entityDescription(
for: entity,
initializer: CoreStoreSchema.firstPassCreateEntityDescription
)
entityDescriptionsByEntity[entity] = (entityDescription.copy() as! NSEntityDescription)
}
CoreStoreSchema.secondPassConnectRelationshipAttributes(for: entityDescriptionsByEntity)
CoreStoreSchema.thirdPassConnectInheritanceTree(for: entityDescriptionsByEntity)
rawModel.entities = entityDescriptionsByEntity.values.sorted(by: { $0.name! < $1.name! })
for (configuration, entities) in self.entitiesByConfiguration {
rawModel.setEntities(
entities
.map({ entityDescriptionsByEntity[$0]! })
.sorted(by: { $0.name! < $1.name! }),
forConfigurationName: configuration
)
}
self.cachedRawModel = rawModel
return rawModel
}
// MARK: Internal // MARK: Internal
// MARK: - AnyEntity // MARK: - AnyEntity
internal struct AnyEntity: EntityProtocol, Hashable { internal struct AnyEntity: DynamicEntity, Hashable {
internal init(_ entity: EntityProtocol) { internal init(_ entity: DynamicEntity) {
self.type = entity.type self.type = entity.type
self.entityName = entity.entityName self.entityName = entity.entityName
@@ -97,7 +146,7 @@ public final class DynamicModel {
^ self.entityName.hashValue ^ self.entityName.hashValue
} }
// MARK: EntityProtocol // MARK: DynamicEntity
internal let type: CoreStoreObject.Type internal let type: CoreStoreObject.Type
internal let entityName: EntityName internal let entityName: EntityName
@@ -106,41 +155,30 @@ public final class DynamicModel {
// MARK: - // MARK: -
internal func createModel() -> NSManagedObjectModel { internal let entitiesByConfiguration: [String: Set<AnyEntity>]
// MARK: Private
private static let barrierQueue = DispatchQueue.concurrent("com.coreStore.coreStoreDataModelBarrierQueue")
private let allEntities: Set<AnyEntity>
private var entityDescriptionsByEntity: [CoreStoreSchema.AnyEntity: NSEntityDescription] = [:]
private weak var cachedRawModel: NSManagedObjectModel?
private func entityDescription(for entity: CoreStoreSchema.AnyEntity, initializer: (CoreStoreSchema.AnyEntity) -> NSEntityDescription) -> NSEntityDescription {
let model = NSManagedObjectModel() if let cachedEntityDescription = self.entityDescriptionsByEntity[entity] {
let entityDescriptionsByEntity: [AnyEntity: NSEntityDescription] = ModelCache.performUpdate {
var entityDescriptionsByEntity: [AnyEntity: NSEntityDescription] = [:] return cachedEntityDescription
for entity in self.allEntities {
let entityDescription = ModelCache.entityDescription(
for: entity,
initializer: DynamicModel.firstPassCreateEntityDescription
)
entityDescriptionsByEntity[entity] = entityDescription
}
DynamicModel.secondPassConnectRelationshipAttributes(for: entityDescriptionsByEntity)
DynamicModel.thirdPassConnectInheritanceTree(for: entityDescriptionsByEntity)
return entityDescriptionsByEntity
} }
model.entities = entityDescriptionsByEntity.values.sorted(by: { $0.name! < $1.name! }) let entityDescription = withoutActuallyEscaping(initializer, do: { $0(entity) })
for (configuration, entities) in self.entitiesByConfiguration { self.entityDescriptionsByEntity[entity] = entityDescription
return entityDescription
model.setEntities(
entities
.map({ entityDescriptionsByEntity[$0]! })
.sorted(by: { $0.name! < $1.name! }),
forConfigurationName: configuration
)
}
return model
} }
private static func firstPassCreateEntityDescription(from entity: AnyEntity) -> NSEntityDescription {
// MARK: FilePrivate
fileprivate static func firstPassCreateEntityDescription(from entity: AnyEntity) -> NSEntityDescription {
let entityDescription = NSEntityDescription() let entityDescription = NSEntityDescription()
entityDescription.anyEntity = entity entityDescription.anyEntity = entity
@@ -186,7 +224,7 @@ public final class DynamicModel {
return entityDescription return entityDescription
} }
fileprivate static func secondPassConnectRelationshipAttributes(for entityDescriptionsByEntity: [AnyEntity: NSEntityDescription]) { private static func secondPassConnectRelationshipAttributes(for entityDescriptionsByEntity: [AnyEntity: NSEntityDescription]) {
var relationshipsByNameByEntity: [AnyEntity: [String: NSRelationshipDescription]] = [:] var relationshipsByNameByEntity: [AnyEntity: [String: NSRelationshipDescription]] = [:]
for (entity, entityDescription) in entityDescriptionsByEntity { for (entity, entityDescription) in entityDescriptionsByEntity {
@@ -207,7 +245,7 @@ public final class DynamicModel {
if matchedEntities.isEmpty { if matchedEntities.isEmpty {
CoreStore.abort( CoreStore.abort(
"No \(cs_typeName("Entity<\(type)>")) instance found in the \(cs_typeName(DynamicModel.self))." "No \(cs_typeName("Entity<\(type)>")) instance found in the \(cs_typeName(CoreStoreSchema.self))."
) )
} }
else { else {
@@ -277,7 +315,7 @@ public final class DynamicModel {
} }
} }
fileprivate static func thirdPassConnectInheritanceTree(for entityDescriptionsByEntity: [AnyEntity: NSEntityDescription]) { private static func thirdPassConnectInheritanceTree(for entityDescriptionsByEntity: [AnyEntity: NSEntityDescription]) {
func connectBaseEntity(mirror: Mirror, entityDescription: NSEntityDescription) { func connectBaseEntity(mirror: Mirror, entityDescription: NSEntityDescription) {
@@ -304,40 +342,4 @@ public final class DynamicModel {
) )
} }
} }
// MARK: Private
private let version: String
private let allEntities: Set<AnyEntity>
private let entitiesByConfiguration: [String: Set<AnyEntity>]
}
// MARK: - ModelCache
fileprivate enum ModelCache {
fileprivate static func performUpdate<T>(_ closure: () -> T) -> T {
return self.barrierQueue.cs_barrierSync(closure)
}
fileprivate static func entityDescription(for entity: DynamicModel.AnyEntity, initializer: (DynamicModel.AnyEntity) -> NSEntityDescription) -> NSEntityDescription {
if let cachedEntityDescription = self.entityDescriptionsByEntity[entity] {
return cachedEntityDescription
}
let entityDescription = withoutActuallyEscaping(initializer, do: { $0(entity) })
self.entityDescriptionsByEntity[entity] = entityDescription
return entityDescription
}
// MARK: Private
private static let barrierQueue = DispatchQueue.concurrent("com.coreStore.modelCacheBarrierQueue")
private static var entityDescriptionsByEntity: [DynamicModel.AnyEntity: NSEntityDescription] = [:]
} }

View File

@@ -0,0 +1,37 @@
//
// DynamicSchema.swift
// CoreStore
//
// Copyright © 2017 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 CoreData
import Foundation
// MARK: - DynamicSchema
public protocol DynamicSchema {
var modelVersion: ModelVersion { get }
func rawModel() -> NSManagedObjectModel
}

View File

@@ -0,0 +1,54 @@
//
// LegacyXcodeDataModel.swift
// CoreStore
//
// Copyright © 2017 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 CoreData
import Foundation
// MARK: - LegacyXcodeDataModel
public final class LegacyXcodeDataModel: DynamicSchema {
public required init(modelName: ModelVersion, model: NSManagedObjectModel) {
self.modelVersion = modelName
self.model = model
}
// MARK: DynamicSchema
public let modelVersion: ModelVersion
public func rawModel() -> NSManagedObjectModel {
return self.model
}
// MARK: Private
private let model: NSManagedObjectModel
}

View File

@@ -0,0 +1,78 @@
//
// XcodeDataModel.swift
// CoreStore
//
// Copyright © 2017 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 CoreData
import Foundation
// MARK: - XcodeDataModel
public final class XcodeDataModel: DynamicSchema {
public required init(modelVersion: ModelVersion, modelVersionFileURL: URL) {
CoreStore.assert(
NSManagedObjectModel(contentsOf: modelVersionFileURL) != nil,
"Could not find the \"\(modelVersion).mom\" version file for the model at URL \"\(modelVersionFileURL)\"."
)
self.modelVersion = modelVersion
self.modelVersionFileURL = modelVersionFileURL
}
// MARK: DynamicSchema
public let modelVersion: ModelVersion
public func rawModel() -> NSManagedObjectModel {
if let cachedRawModel = self.cachedRawModel {
return cachedRawModel
}
if let rawModel = NSManagedObjectModel(contentsOf: self.modelVersionFileURL) {
self.cachedRawModel = rawModel
return rawModel
}
CoreStore.abort("Could not create an \(cs_typeName(NSManagedObjectModel.self)) from the model at URL \"\(self.modelVersionFileURL)\".")
}
// MARK: Internal
internal let modelVersionFileURL: URL
private lazy var rootModelFileURL: URL = cs_lazy { [unowned self] in
return self.modelVersionFileURL.deletingLastPathComponent()
}
// MARK: Private
private weak var cachedRawModel: NSManagedObjectModel?
}

View File

@@ -28,9 +28,9 @@ import Foundation
import ObjectiveC import ObjectiveC
// MARK: - EntityProtocol // MARK: - DynamicEntity
public protocol EntityProtocol { public protocol DynamicEntity {
var type: CoreStoreObject.Type { get } var type: CoreStoreObject.Type { get }
var entityName: EntityName { get } var entityName: EntityName { get }
@@ -39,7 +39,7 @@ public protocol EntityProtocol {
// MARK: Entity // MARK: Entity
public struct Entity<O: CoreStoreObject>: EntityProtocol { public struct Entity<O: CoreStoreObject>: DynamicEntity, Hashable {
public init(_ entityName: String) { public init(_ entityName: String) {
@@ -47,136 +47,54 @@ public struct Entity<O: CoreStoreObject>: EntityProtocol {
self.entityName = entityName self.entityName = entityName
} }
// MARK: EntityProtocol public init(_ type: O.Type, _ entityName: String) {
self.type = type
self.entityName = entityName
}
// MARK: - VersionHash
public struct VersionHash: ExpressibleByArrayLiteral {
let hash: Data
public init(_ hash: Data) {
self.hash = hash
}
// MARK: ExpressibleByArrayLiteral
public typealias Element = UInt8
public init(arrayLiteral elements: UInt8...) {
self.hash = Data(bytes: elements)
}
}
// MARK: DynamicEntity
public let type: CoreStoreObject.Type public let type: CoreStoreObject.Type
public let entityName: EntityName public let entityName: EntityName
}
// MARK: - EntityIdentifier
internal struct EntityIdentifier: Hashable {
// MARK: - Category
internal enum Category: Int {
case coreData
case coreStore
}
// MARK: -
internal let category: Category
internal let interfacedClassName: String
internal init(_ type: NSManagedObject.Type) {
self.category = .coreData
self.interfacedClassName = String(reflecting: type)
}
internal init(_ type: CoreStoreObject.Type) {
self.category = .coreStore
self.interfacedClassName = String(reflecting: type)
}
internal init(_ type: DynamicObject.Type) {
switch type {
case let type as NSManagedObject.Type:
self.init(type)
case let type as CoreStoreObject.Type:
self.init(type)
default:
CoreStore.abort("\(cs_typeName(DynamicObject.self)) is not meant to be implemented by external types.")
}
}
internal init(_ entityDescription: NSEntityDescription) {
if let entity = entityDescription.anyEntity {
self.category = .coreStore
self.interfacedClassName = NSStringFromClass(entity.type)
}
else {
self.category = .coreData
self.interfacedClassName = entityDescription.managedObjectClassName!
}
}
// MARK: Equatable // MARK: Equatable
static func == (lhs: EntityIdentifier, rhs: EntityIdentifier) -> Bool { public static func == (lhs: Entity, rhs: Entity) -> Bool {
return lhs.category == rhs.category return lhs.type == rhs.type
&& lhs.interfacedClassName == rhs.interfacedClassName && lhs.entityName == rhs.entityName
} }
// MARK: Hashable // MARK: Hashable
var hashValue: Int { public var hashValue: Int {
return self.category.hashValue return ObjectIdentifier(self.type).hashValue
^ self.interfacedClassName.hashValue
}
}
// MARK: - NSEntityDescription
internal extension NSEntityDescription {
@nonobjc
internal var anyEntity: DynamicModel.AnyEntity? {
get {
guard let userInfo = self.userInfo,
let typeName = userInfo[UserInfoKey.CoreStoreManagedObjectTypeName] as! String?,
let entityName = userInfo[UserInfoKey.CoreStoreManagedObjectEntityName] as! String? else {
return nil
}
return DynamicModel.AnyEntity(
type: NSClassFromString(typeName) as! CoreStoreObject.Type,
entityName: entityName
)
}
set {
if let newValue = newValue {
self.userInfo = [
UserInfoKey.CoreStoreManagedObjectTypeName: NSStringFromClass(newValue.type),
UserInfoKey.CoreStoreManagedObjectEntityName: newValue.entityName
]
}
else {
self.userInfo = [:]
}
}
}
// MARK: Private
// MARK: - UserInfoKey
fileprivate enum UserInfoKey {
fileprivate static let CoreStoreManagedObjectTypeName = "CoreStoreManagedObjectTypeName"
fileprivate static let CoreStoreManagedObjectEntityName = "CoreStoreManagedObjectEntityName"
} }
} }

View File

@@ -0,0 +1,227 @@
//
// SchemaHistory.swift
// CoreStore
//
// Copyright © 2017 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 CoreData
import Foundation
// MARK: - SchemaHistory
public final class SchemaHistory: ExpressibleByArrayLiteral {
public let currentModelVersion: ModelVersion
public let migrationChain: MigrationChain
public convenience init(modelName: XcodeDataModelFileName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) {
guard let modelFilePath = bundle.path(forResource: modelName, ofType: "momd") else {
// For users migrating from very old Xcode versions: Old xcdatamodel files are not contained inside xcdatamodeld (with a "d"), and will thus fail this check. If that was the case, create a new xcdatamodeld file and copy all contents into the new model.
let foundModels = bundle
.paths(forResourcesOfType: "momd", inDirectory: nil)
.map({ ($0 as NSString).lastPathComponent })
CoreStore.abort("Could not find \"\(modelName).momd\" from the bundle \"\(bundle.bundleIdentifier ?? "<nil>")\". Other model files in bundle: \(foundModels.coreStoreDumpString)")
}
let modelFileURL = URL(fileURLWithPath: modelFilePath)
let versionInfoPlistURL = modelFileURL.appendingPathComponent("VersionInfo.plist", isDirectory: false)
guard let versionInfo = NSDictionary(contentsOf: versionInfoPlistURL),
let versionHashes = versionInfo["NSManagedObjectModel_VersionHashes"] as? [String: AnyObject] else {
CoreStore.abort("Could not load \(cs_typeName(NSManagedObjectModel.self)) metadata from path \"\(versionInfoPlistURL)\".")
}
let modelVersions = Set(versionHashes.keys)
let modelVersionHints = migrationChain.leafVersions
let currentModelVersion: String
if let plistModelVersion = versionInfo["NSManagedObjectModel_CurrentVersionName"] as? String,
modelVersionHints.isEmpty || modelVersionHints.contains(plistModelVersion) {
currentModelVersion = plistModelVersion
}
else if let resolvedVersion = modelVersions.intersection(modelVersionHints).first {
CoreStore.log(
.warning,
message: "The \(cs_typeName(MigrationChain.self)) leaf versions do not include the model file's current version. Resolving to version \"\(resolvedVersion)\"."
)
currentModelVersion = resolvedVersion
}
else if let resolvedVersion = modelVersions.first ?? modelVersionHints.first {
if !modelVersionHints.isEmpty {
CoreStore.log(
.warning,
message: "The \(cs_typeName(MigrationChain.self)) leaf versions do not include any of the model file's embedded versions. Resolving to version \"\(resolvedVersion)\"."
)
}
currentModelVersion = resolvedVersion
}
else {
CoreStore.abort("No model files were found in URL \"\(modelFileURL)\".")
}
var allSchema: [DynamicSchema] = []
for modelVersion in modelVersions {
let fileURL = modelFileURL.appendingPathComponent("\(modelVersion).mom", isDirectory: false)
allSchema.append(XcodeDataModel(modelVersion: modelVersion, modelVersionFileURL: fileURL))
}
self.init(
allSchema: allSchema,
migrationChain: migrationChain,
exactCurrentModelVersion: currentModelVersion
)
}
public convenience init(_ schema: DynamicSchema, _ otherSchema: DynamicSchema..., migrationChain: MigrationChain = nil, exactCurrentModelVersion: String? = nil) {
self.init(
allSchema: [schema] + otherSchema,
migrationChain: migrationChain,
exactCurrentModelVersion: exactCurrentModelVersion
)
}
public required init(allSchema: [DynamicSchema], migrationChain: MigrationChain = nil, exactCurrentModelVersion: String? = nil) {
if allSchema.isEmpty {
CoreStore.abort("The \"allSchema\" argument of the \(cs_typeName(SchemaHistory.self)) initializer cannot be empty.")
}
var schemaByVersion: [ModelVersion: DynamicSchema] = [:]
for schema in allSchema {
let modelVersion = schema.modelVersion
CoreStore.assert(
schemaByVersion[modelVersion] == nil,
"Multiple model schema found for model version \"\(modelVersion)\"."
)
schemaByVersion[modelVersion] = schema
}
let modelVersions = Set(schemaByVersion.keys)
let currentModelVersion: ModelVersion
if let exactCurrentModelVersion = exactCurrentModelVersion {
if !migrationChain.isEmpty && !migrationChain.contains(exactCurrentModelVersion) {
CoreStore.abort("An \"exactCurrentModelVersion\" argument was provided to \(cs_typeName(SchemaHistory.self)) initializer but a matching schema could not be found from the provided \(cs_typeName(MigrationChain.self)).")
}
if schemaByVersion[exactCurrentModelVersion] == nil {
CoreStore.abort("An \"exactCurrentModelVersion\" argument was provided to \(cs_typeName(SchemaHistory.self)) initializer but a matching schema could not be found from the \(cs_typeName(DynamicSchema.self)) list.")
}
currentModelVersion = exactCurrentModelVersion
}
else if migrationChain.isEmpty && schemaByVersion.count == 1 {
currentModelVersion = schemaByVersion.keys.first!
}
else {
let candidateVersions = modelVersions.intersection(migrationChain.leafVersions)
switch candidateVersions.count {
case 0:
CoreStore.abort("None of the \(cs_typeName(MigrationChain.self)) leaf versions provided to the \(cs_typeName(SchemaHistory.self)) initializer matches any scheme from the \(cs_typeName(DynamicSchema.self)) list.")
case 1:
currentModelVersion = candidateVersions.first!
default:
CoreStore.abort("Could not resolve the \(cs_typeName(SchemaHistory.self)) current model version because the \(cs_typeName(MigrationChain.self)) have ambiguous leaf versions: \(candidateVersions)")
}
}
self.schemaByVersion = schemaByVersion
self.migrationChain = migrationChain
self.currentModelVersion = currentModelVersion
self.rawModel = schemaByVersion[currentModelVersion]!.rawModel()
}
// MARK: ExpressibleByArrayLiteral
public typealias Element = DynamicSchema
public convenience init(arrayLiteral elements: DynamicSchema...) {
self.init(
allSchema: elements,
migrationChain: MigrationChain(elements.map({ $0.modelVersion })),
exactCurrentModelVersion: nil
)
}
// MARK: Internal
internal let schemaByVersion: [ModelVersion: DynamicSchema]
internal let rawModel: NSManagedObjectModel
internal private(set) lazy var entityDescriptionsByEntityIdentifier: [EntityIdentifier: NSEntityDescription] = cs_lazy { [unowned self] in
var mapping: [EntityIdentifier: NSEntityDescription] = [:]
self.rawModel.entities.forEach { (entityDescription) in
let entityIdentifier = EntityIdentifier(entityDescription)
mapping[entityIdentifier] = entityDescription
}
return mapping
}
internal func rawModel(for modelVersion: ModelVersion) -> NSManagedObjectModel? {
if modelVersion == self.currentModelVersion {
return self.rawModel
}
return self.schemaByVersion[modelVersion]?.rawModel()
}
internal func schema(for storeMetadata: [String: Any]) -> DynamicSchema? {
guard let modelHashes = storeMetadata[NSStoreModelVersionHashesKey] as! [String: Data]? else {
return nil
}
for (_, schema) in self.schemaByVersion {
let rawModel = schema.rawModel()
if modelHashes == rawModel.entityVersionHashesByName {
return schema
}
}
return nil
}
internal func mergedModels() -> [NSManagedObjectModel] {
return self.schemaByVersion.values.map({ $0.rawModel() })
}
}

View File

@@ -233,7 +233,7 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
// MARK: Internal // MARK: Internal
internal static let defaultRootDirectory: URL = { internal static let defaultRootDirectory: URL = cs_lazy {
#if os(tvOS) #if os(tvOS)
let systemDirectorySearchPath = FileManager.SearchPathDirectory.cachesDirectory let systemDirectorySearchPath = FileManager.SearchPathDirectory.cachesDirectory
@@ -244,7 +244,7 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
return FileManager.default.urls( return FileManager.default.urls(
for: systemDirectorySearchPath, for: systemDirectorySearchPath,
in: .userDomainMask).first! in: .userDomainMask).first!
}() }
internal static let defaultFileURL = LegacySQLiteStore.defaultRootDirectory internal static let defaultFileURL = LegacySQLiteStore.defaultRootDirectory
.appendingPathComponent(DataStack.applicationName, isDirectory: false) .appendingPathComponent(DataStack.applicationName, isDirectory: false)

View File

@@ -230,7 +230,7 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
// MARK: Internal // MARK: Internal
internal static let defaultRootDirectory: URL = { internal static let defaultRootDirectory: URL = cs_lazy {
#if os(tvOS) #if os(tvOS)
let systemDirectorySearchPath = FileManager.SearchPathDirectory.cachesDirectory let systemDirectorySearchPath = FileManager.SearchPathDirectory.cachesDirectory
@@ -246,7 +246,7 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
Bundle.main.bundleIdentifier ?? "com.CoreStore.DataStack", Bundle.main.bundleIdentifier ?? "com.CoreStore.DataStack",
isDirectory: true isDirectory: true
) )
}() }
internal static let defaultFileURL = SQLiteStore.defaultRootDirectory internal static let defaultFileURL = SQLiteStore.defaultRootDirectory
.appendingPathComponent( .appendingPathComponent(