diff --git a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/MigrationsDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/MigrationsDemoViewController.swift index ecf780e..4e823b7 100644 --- a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/MigrationsDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/MigrationsDemoViewController.swift @@ -241,7 +241,7 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD let count = dataStack.queryValue( From(model.entityType), - Select(.count(#keyPath(OrganismProtocol.dna))))! + Select(.count(#keyPath(OrganismV1.dna))))! if count > 0 { self.setEnabled(true) diff --git a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismProtocol.swift b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismProtocol.swift index 45e1271..918939e 100644 --- a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismProtocol.swift +++ b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismProtocol.swift @@ -13,4 +13,4 @@ protocol OrganismProtocol: class { var dna: Int64 { get set } func mutate() -} \ No newline at end of file +} diff --git a/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift index ae748f4..469dd10 100644 --- a/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift @@ -140,7 +140,7 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec mapView.setCenter(object.coordinate, animated: true) mapView.selectAnnotation(object, animated: true) - if changedPersistentKeys.contains(#keyPath(Place.latitude) || changedPersistentKeys.contains(#keyPath(Place.longitude)) { + if changedPersistentKeys.contains(#keyPath(Place.latitude)) || changedPersistentKeys.contains(#keyPath(Place.longitude)) { self.geocode(place: object) } diff --git a/CoreStoreTests/ImportTests.swift b/CoreStoreTests/ImportTests.swift index 22584a3..3435b97 100644 --- a/CoreStoreTests/ImportTests.swift +++ b/CoreStoreTests/ImportTests.swift @@ -904,12 +904,12 @@ extension TestEntity1: ImportableUniqueObject { typealias ImportSource = [String: Any] - static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool { + static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool { return source["skip_insert"] == nil } - func didInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws { + func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws { if let _ = source["throw_on_insert"] { @@ -951,12 +951,12 @@ extension TestEntity1: ImportableUniqueObject { } } - static func shouldUpdateFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool { + static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool { return source["skip_update"] == nil } - static func uniqueIDFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> NSNumber? { + static func uniqueID(from source: ImportSource, in transaction: BaseDataTransaction) throws -> NSNumber? { if let _ = source["throw_on_id"] { @@ -965,7 +965,7 @@ extension TestEntity1: ImportableUniqueObject { return source[(#keyPath(TestEntity1.testEntityID))] as? NSNumber } - func updateFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws { + func update(from source: ImportSource, in transaction: BaseDataTransaction) throws { if let _ = source["throw_on_update"] { diff --git a/README.md b/README.md index 57e5788..e7cf20f 100644 --- a/README.md +++ b/README.md @@ -737,8 +737,8 @@ You can even use external types from popular 3rd-party JSON libraries ([SwiftyJS ```swift public protocol ImportableObject: class { typealias ImportSource - static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool - func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws + static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool + func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws } ``` First, set `ImportSource` to the expected type of the data source: @@ -756,9 +756,9 @@ CoreStore.beginAsynchronous { (transaction) -> Void in // ... } ``` -The actual extraction and assignment of values should be implemented in the `didInsertFromImportSource(...)` method of the `ImportableObject` protocol: +The actual extraction and assignment of values should be implemented in the `didInsert(from:in:)` method of the `ImportableObject` protocol: ```swift -func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws { +func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws { self.name = source["name"] as? NSString self.age = source["age"] as? NSNumber // ... @@ -775,11 +775,11 @@ CoreStore.beginAsynchronous { (transaction) -> Void in // ... } ``` -Doing so tells the transaction to iterate through the array of import sources and calls `shouldInsertFromImportSource(...)` on the `ImportableObject` to determine which instances should be created. You can do validations and return `false` from `shouldInsertFromImportSource(...)` if you want to skip importing from a source and continue on with the other sources in the array. +Doing so tells the transaction to iterate through the array of import sources and calls `shouldInsert(from:in:)` on the `ImportableObject` to determine which instances should be created. You can do validations and return `false` from `shouldInsert(from:in:)` if you want to skip importing from a source and continue on with the other sources in the array. -If on the other hand, your validation in one of the sources failed in such a manner that all other sources should also be cancelled, you can `throw` from within `didInsertFromImportSource(...)`: +If on the other hand, your validation in one of the sources failed in such a manner that all other sources should also be cancelled, you can `throw` from within `didInsert(from:in:)`: ```swift -func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws { +func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws { self.name = source["name"] as? NSString self.age = source["age"] as? NSNumber // ... @@ -817,11 +817,11 @@ public protocol ImportableUniqueObject: ImportableObject { static var uniqueIDKeyPath: String { get } var uniqueIDValue: UniqueIDType { get set } - static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool - static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool - static func uniqueIDFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> UniqueIDType? - func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws - func updateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws + static func shouldInsert(from source: ImportSource, inn transaction: BaseDataTransaction) -> Bool + static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool + static func uniqueID(from source: ImportSource, in transaction: BaseDataTransaction) throws -> UniqueIDType? + func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws + func update(from source: ImportSource, in transaction: BaseDataTransaction) throws } ``` Notice that it has the same insert methods as `ImportableObject`, with additional methods for updates and for specifying the unique ID: @@ -833,11 +833,11 @@ var uniqueIDValue: NSNumber { get { return self.personID } set { self.personID = newValue } } -class func uniqueIDFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> NSNumber? { +class func uniqueID(from source: ImportSource, in transaction: BaseDataTransaction) throws -> NSNumber? { return source["id"] as? NSNumber } ``` -For `ImportableUniqueObject`, the extraction and assignment of values should be implemented from the `updateFromImportSource(...)` method. The `didInsertFromImportSource(...)` by default calls `updateFromImportSource(...)`, but you can separate the implementation for inserts and updates if needed. +For `ImportableUniqueObject`, the extraction and assignment of values should be implemented from the `update(from:in:)` method. The `didInsert(from:in:)` by default calls `update(from:in:)`, but you can separate the implementation for inserts and updates if needed. You can then create/update an object by calling a transaction's `importUniqueObject(...)` method: ```swift @@ -863,7 +863,7 @@ CoreStore.beginAsynchronous { (transaction) -> Void in } ``` As with `ImportableObject`, you can control wether to skip importing an object by implementing -`shouldInsertFromImportSource(...)` and `shouldUpdateFromImportSource(...)`, or to cancel all objects by `throw`ing an error from the `uniqueIDFromImportSource(...)`, `didInsertFromImportSource(...)` or `updateFromImportSource(...)` methods. +`shouldInsert(from:in:)` and `shouldUpdate(from:in:)`, or to cancel all objects by `throw`ing an error from the `uniqueID(from:in:)`, `didInsert(from:in:)` or `update(from:in:)` methods. ## Fetching and Querying diff --git a/Sources/Importing/BaseDataTransaction+Importing.swift b/Sources/Importing/BaseDataTransaction+Importing.swift index a2dcd05..f1ff670 100644 --- a/Sources/Importing/BaseDataTransaction+Importing.swift +++ b/Sources/Importing/BaseDataTransaction+Importing.swift @@ -50,13 +50,13 @@ public extension BaseDataTransaction { return try autoreleasepool { - guard T.shouldInsertFromImportSource(source, inTransaction: self) else { + guard T.shouldInsert(from: source, in: self) else { return nil } let object = self.create(into) - try object.didInsertFromImportSource(source, inTransaction: self) + try object.didInsert(from: source, in: self) return object } } @@ -79,12 +79,12 @@ public extension BaseDataTransaction { try autoreleasepool { - guard T.shouldInsertFromImportSource(source, inTransaction: self) else { + guard T.shouldInsert(from: source, in: self) else { return } - try object.didInsertFromImportSource(source, inTransaction: self) + try object.didInsert(from: source, in: self) } } @@ -109,7 +109,7 @@ public extension BaseDataTransaction { return try sourceArray.flatMap { (source) -> T? in - guard T.shouldInsertFromImportSource(source, inTransaction: self) else { + guard T.shouldInsert(from: source, in: self) else { return nil } @@ -117,7 +117,7 @@ public extension BaseDataTransaction { return try autoreleasepool { let object = self.create(into) - try object.didInsertFromImportSource(source, inTransaction: self) + try object.didInsert(from: source, in: self) return object } } @@ -144,31 +144,31 @@ public extension BaseDataTransaction { return try autoreleasepool { let uniqueIDKeyPath = T.uniqueIDKeyPath - guard let uniqueIDValue = try T.uniqueIDFromImportSource(source, inTransaction: self) else { + guard let uniqueIDValue = try T.uniqueID(from: source, in: self) else { return nil } if let object = self.fetchOne(From(), Where(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) { - guard T.shouldUpdateFromImportSource(source, inTransaction: self) else { + guard T.shouldUpdate(from: source, in: self) else { return nil } - try object.updateFromImportSource(source, inTransaction: self) + try object.update(from: source, in: self) return object } else { - guard T.shouldInsertFromImportSource(source, inTransaction: self) else { + guard T.shouldInsert(from: source, in: self) else { return nil } let object = self.create(into) object.uniqueIDValue = uniqueIDValue - try object.didInsertFromImportSource(source, inTransaction: self) + try object.didInsert(from: source, in: self) return object } } @@ -201,7 +201,7 @@ public extension BaseDataTransaction { return try sourceArray.flatMap { (source) -> T.UniqueIDType? in - guard let uniqueIDValue = try T.uniqueIDFromImportSource(source, inTransaction: self) else { + guard let uniqueIDValue = try T.uniqueID(from: source, in: self) else { return nil } @@ -221,12 +221,12 @@ public extension BaseDataTransaction { let uniqueIDValue = object.uniqueIDValue guard let source = mapping.removeValue(forKey: uniqueIDValue), - T.shouldUpdateFromImportSource(source, inTransaction: self) else { + T.shouldUpdate(from: source, in: self) else { return } - try object.updateFromImportSource(source, inTransaction: self) + try object.update(from: source, in: self) objects[uniqueIDValue] = object } } @@ -235,14 +235,14 @@ public extension BaseDataTransaction { try autoreleasepool { - guard T.shouldInsertFromImportSource(source, inTransaction: self) else { + guard T.shouldInsert(from: source, in: self) else { return } let object = self.create(into) object.uniqueIDValue = uniqueIDValue - try object.didInsertFromImportSource(source, inTransaction: self) + try object.didInsert(from: source, in: self) objects[uniqueIDValue] = object } diff --git a/Sources/Importing/ImportableObject.swift b/Sources/Importing/ImportableObject.swift index 53bf2c8..2dcd018 100644 --- a/Sources/Importing/ImportableObject.swift +++ b/Sources/Importing/ImportableObject.swift @@ -62,14 +62,23 @@ public protocol ImportableObject: class { - parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed. - returns: `true` if an object should be created from `source`. Return `false` to ignore. */ - static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool + static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool /** Implements the actual importing of data from `source`. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importObjects(:sourceArray:)` call to be cancelled. - parameter source: the object to import from - parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed. - */ + */ + func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws + + + // MARK: Deprecated + + @available(*, deprecated: 3.0.0, renamed: "shouldInsert(from:in:)") + static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool + + @available(*, deprecated: 3.0.0, renamed: "didInsert(from:in:)") func didInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws } @@ -78,8 +87,21 @@ public protocol ImportableObject: class { public extension ImportableObject { - static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool { + static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool { return true } + + + // MARK: Deprecated + + static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool { + + return Self.shouldInsert(from: source, in: transaction) + } + + func didInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws { + + try self.didInsert(from: source, in: transaction) + } } diff --git a/Sources/Importing/ImportableUniqueObject.swift b/Sources/Importing/ImportableUniqueObject.swift index 9f47677..7c54cb4 100644 --- a/Sources/Importing/ImportableUniqueObject.swift +++ b/Sources/Importing/ImportableUniqueObject.swift @@ -72,13 +72,13 @@ public protocol ImportableUniqueObject: ImportableObject { var uniqueIDValue: UniqueIDType { get set } /** - Return `true` if an object should be created from `source`. Return `false` to ignore and skip `source`. The default implementation returns the value returned by the `shouldUpdateFromImportSource(:inTransaction:)` implementation. + Return `true` if an object should be created from `source`. Return `false` to ignore and skip `source`. The default implementation returns the value returned by the `shouldUpdate(from:in:)` implementation. - parameter source: the object to import from - parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed. - returns: `true` if an object should be created from `source`. Return `false` to ignore. */ - static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool + static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool /** Return `true` if an object should be updated from `source`. Return `false` to ignore and skip `source`. The default implementation returns `true`. @@ -87,24 +87,24 @@ public protocol ImportableUniqueObject: ImportableObject { - parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed. - returns: `true` if an object should be updated from `source`. Return `false` to ignore. */ - static func shouldUpdateFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool + static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool /** - Return the unique ID as extracted from `source`. This method is called before `shouldInsertFromImportSource(...)` or `shouldUpdateFromImportSource(...)`. Return `nil` to skip importing from `source`. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled. + Return the unique ID as extracted from `source`. This method is called before `shouldInsert(from:in:)` or `shouldUpdate(from:in:)`. Return `nil` to skip importing from `source`. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled. - parameter source: the object to import from - parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed. - returns: the unique ID as extracted from `source`, or `nil` to skip importing from `source`. */ - static func uniqueIDFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> UniqueIDType? + static func uniqueID(from source: ImportSource, in transaction: BaseDataTransaction) throws -> UniqueIDType? /** - Implements the actual importing of data from `source`. This method is called just after the object is created and assigned its unique ID as returned from `uniqueIDFromImportSource(...)`. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled. The default implementation simply calls `updateFromImportSource(...)`. + Implements the actual importing of data from `source`. This method is called just after the object is created and assigned its unique ID as returned from `uniqueID(from:in:)`. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled. The default implementation simply calls `update(from:in:)`. - parameter source: the object to import from - parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed. */ - func didInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws + func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws /** Implements the actual importing of data from `source`. This method is called just after the existing object is fetched using its unique ID. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled. @@ -112,6 +112,24 @@ public protocol ImportableUniqueObject: ImportableObject { - parameter source: the object to import from - parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed. */ + func update(from source: ImportSource, in transaction: BaseDataTransaction) throws + + + // MARK: Deprecated + + @available(*, deprecated: 3.0.0, renamed: "shouldInsert(from:in:)") + static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool + + @available(*, deprecated: 3.0.0, renamed: "shouldUpdate(from:in:)") + static func shouldUpdateFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool + + @available(*, deprecated: 3.0.0, renamed: "uniqueID(from:in:)") + static func uniqueIDFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> UniqueIDType? + + @available(*, deprecated: 3.0.0, renamed: "didInsert(from:in:)") + func didInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws + + @available(*, deprecated: 3.0.0, renamed: "update(from:in:)") func updateFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws } @@ -120,18 +138,46 @@ public protocol ImportableUniqueObject: ImportableObject { public extension ImportableUniqueObject { - static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool { + static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool { - return self.shouldUpdateFromImportSource(source, inTransaction: transaction) + return Self.shouldUpdate(from: source, in: transaction) } - static func shouldUpdateFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool { + static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool{ return true } + func didInsert(from source: Self.ImportSource, in transaction: BaseDataTransaction) throws { + + try self.update(from: source, in: transaction) + } + + + // MARK: Deprecated + + static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool { + + return Self.shouldInsert(from: source, in: transaction) + } + + static func shouldUpdateFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool { + + return Self.shouldUpdate(from: source, in: transaction) + } + + static func uniqueIDFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> UniqueIDType? { + + return try Self.uniqueID(from: source, in: transaction) + } + func didInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws { - try self.updateFromImportSource(source, inTransaction: transaction) + try self.didInsert(from: source, in: transaction) + } + + func updateFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws { + + try self.update(from: source, in: transaction) } }