CoreStore v7.0.0 Release Notes
Release Date: 2019-10-22 // over 4 years 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 last6.3.2
release if you still need Swift 5.0.🗄 Deprecations
⏪ The
CoreStore
-namespaced API has been deprecated in favor ofDataStack
method calls. If you are using the global utilities such asCoreStore.defaultStack
andCoreStore.logger
, a newCoreStoreDefaults
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
andUICollectionViews
now have a new ally:ListPublisher
s provide diffable snapshots that make reloading animations very easy and very safe. Say goodbye toUITableViews
andUICollectionViews
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
UITableView
s andUICollectionView
s 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 ofListMonitor
. UnlikeListMonitor
, it does not keep track of minute inserts, deletes, moves, and updates. It simply updates itssnapshot
property which is astruct
storing the list state at a specific point in time. ThisListSnapshot
is then usable with theDiffableDataSource
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 )}
ListSnapshot
s store onlyNSManagedObjectID
s and their sections.ObjectPublisher and ObjectSnapshot
ObjectPublisher
is a more lightweight counterpart ofObjectMonitor
. UnlikeObjectMonitor
, it does not keep track of per-property changes. You can create anObjectPublisher
from the object directly:let objectPublisher: ObjectPublisher\<Person\> = person.asPublisher(in: dataStack)
or by indexing a
ListPublisher
'sListSnapshot
:let objectPublisher = self.listPublisher.snapshot[indexPath]
The
ObjectPublisher
exposes asnapshot
property which returns anObjectSnapshot
, which is a lazily generatedstruct
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, and
ObjectSnapshotall conform to the
ObjectRepresentation` 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. - ⏪