CoreStore v7.0.0 Release Notes

Release Date: 2019-10-22 // over 1 year ago
  • ⚡️ ⚠️This update will break current code. Make sure to read the changes below:

    💥 Breaking Changes

    🚀 Starting version 7.0.0, CoreStore will be using a lot of Swift 5.1 features, both internally and in its public API. You can keep using the last 6.3.2 release if you still need Swift 5.0.

    🗄 Deprecations

    ⏪ The CoreStore-namespaced API has been deprecated in favor of DataStack method calls. If you are using the global utilities such as CoreStore.defaultStack and CoreStore.logger, a new CoreStoreDefaults namespace has been provided:

    • CoreStore.defaultStack -> CoreStoreDefaults.dataStack
    • CoreStore.logger -> CoreStoreDefaults.logger
    • CoreStore.addStorage(...) -> CoreStoreDefaults.dataStack.addStorage(...)
    • CoreStore.fetchAll(...) -> CoreStoreDefaults.dataStack.fetchAll(...)
    • etc.

    If you have been using your own properties to store DataStack references, then you should not be affected by this change.

    🆕 New features

    Backwards-portable DiffableDataSources implementation

    UITableViews and UICollectionViews now have a new ally: ListPublishers provide diffable snapshots that make reloading animations very easy and very safe. Say goodbye to UITableViews and UICollectionViews reload errors!

    🍎 DiffableDataSource.CollectionView (iOS and macOS) and DiffableDataSource.TableView (iOS)

    self.dataSource = DiffableDataSource.CollectionView\<Person\>( collectionView: self.collectionView, dataStack: CoreStoreDefaults.dataStack, cellProvider: { (collectionView, indexPath, person) inlet cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PersonCell") as! PersonCell cell.setPerson(person) return cell } )

    ⚡️ This is now the recommended method of reloading UITableViews and UICollectionViews because it uses list diffing to update your list views. This means that it is a lot less prone to cause layout errors.

    ListPublisher and ListSnapshot

    ⚡️ ListPublisher is a more lightweight counterpart of ListMonitor. Unlike ListMonitor, it does not keep track of minute inserts, deletes, moves, and updates. It simply updates its snapshot property which is a struct storing the list state at a specific point in time. This ListSnapshot is then usable with the DiffableDataSource utilities (See section above).

    self.listPublisher = dataStack.listPublisher( From\<Person\>() .sectionBy(\.age") { "Age \($0)" } // sections are optional .where(\.title == "Engineer") .orderBy(.ascending(\.lastName)))self.listPublisher.addObserver(self) { [weak self] (listPublisher) in self?.dataSource?.apply( listPublisher.snapshot, animatingDifferences: true )}

    ListSnapshots store only NSManagedObjectIDs and their sections.

    ObjectPublisher and ObjectSnapshot

    ObjectPublisher is a more lightweight counterpart of ObjectMonitor. Unlike ObjectMonitor, it does not keep track of per-property changes. You can create an ObjectPublisher from the object directly:

    let objectPublisher: ObjectPublisher\<Person\> = person.asPublisher(in: dataStack)

    or by indexing a ListPublisher's ListSnapshot:

    let objectPublisher = self.listPublisher.snapshot[indexPath]

    The ObjectPublisher exposes a snapshot property which returns an ObjectSnapshot, which is a lazily generated struct containing fully-copied property values.

    objectPublisher.addObserver(self) { [weak self] (objectPublisher) inlet snapshot: ObjectSnapshot\<Person\> = objectPublisher.snapshot// handle changes}

    This snapshot is completely thread-safe, and any mutations to it will not affect the actual object.

    Intent-based Object representations

    ⏪ CoreStore is slowly moving to abstract object utilities based on usage intent.
    NSManageObject',CoreStoreObject,ObjectPublisher, andObjectSnapshotall conform to theObjectRepresentation` protocol, which allows conversion of each type to another:

    public protocol ObjectRepresentation { associatedtype ObjectType : CoreStore.DynamicObjectfunc objectID() -\> ObjectType.ObjectID func asPublisher(in dataStack: DataStack) -\> ObjectPublisher\<ObjectType\> func asReadOnly(in dataStack: DataStack) -\> ObjectType?func asEditable(in transaction: BaseDataTransaction) -\> ObjectType?func asSnapshot(in dataStack: DataStack) -\> ObjectSnapshot\<ObjectType\>?func asSnapshot(in transaction: BaseDataTransaction) -\> ObjectSnapshot\<ObjectType\>?}

    ObjectMonitor being excluded in this family was intentional; its initialization is complex enough to be an API of its own.