mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-16 22:16:53 +01:00
README update
This commit is contained in:
@@ -54,50 +54,6 @@ extension AsynchronousDataTransaction: CustomDebugStringConvertible, CoreStoreDe
|
||||
}
|
||||
|
||||
|
||||
// MARK: - CloudStorageOptions
|
||||
|
||||
extension CloudStorageOptions: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
|
||||
public var debugDescription: String {
|
||||
|
||||
return formattedDebugDescription(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: CoreStoreDebugStringConvertible
|
||||
|
||||
public var coreStoreDumpString: String {
|
||||
|
||||
var flags = [String]()
|
||||
if self.contains(.recreateLocalStoreOnModelMismatch) {
|
||||
|
||||
flags.append(".recreateLocalStoreOnModelMismatch")
|
||||
}
|
||||
if self.contains(.allowSynchronousLightweightMigration) {
|
||||
|
||||
flags.append(".allowSynchronousLightweightMigration")
|
||||
}
|
||||
switch flags.count {
|
||||
|
||||
case 0:
|
||||
return "[.none]"
|
||||
|
||||
case 1:
|
||||
return "[.\(flags[0])]"
|
||||
|
||||
default:
|
||||
var string = "[\n"
|
||||
string.append(flags.joined(separator: ",\n"))
|
||||
string.indent(1)
|
||||
string.append("\n]")
|
||||
return string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - CoreStoreError
|
||||
|
||||
extension CoreStoreError: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
@@ -74,38 +74,6 @@ extension CoreStore {
|
||||
|
||||
return CoreStoreDefaults.dataStack.addStorage(storage, completion: completion)
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchronously adds a `CloudStorage` to the `CoreStoreDefaults.dataStack`. Migrations are also initiated by default.
|
||||
```
|
||||
guard let storage = ICloudStore(
|
||||
ubiquitousContentName: "MyAppCloudData",
|
||||
ubiquitousContentTransactionLogsSubdirectory: "logs/config1",
|
||||
ubiquitousContainerID: "iCloud.com.mycompany.myapp.containername",
|
||||
ubiquitousPeerToken: "9614d658014f4151a95d8048fb717cf0",
|
||||
configuration: "Config1",
|
||||
cloudStorageOptions: .recreateLocalStoreOnModelMismatch
|
||||
) else {
|
||||
// iCloud is not available on the device
|
||||
return
|
||||
}
|
||||
let migrationProgress = dataStack.addStorage(
|
||||
storage,
|
||||
completion: { result in
|
||||
switch result {
|
||||
case .success(let storage): // ...
|
||||
case .failure(let error): // ...
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
- parameter storage: the cloud storage
|
||||
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `CloudStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
|
||||
*/
|
||||
public static func addStorage<T: CloudStorage>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
|
||||
|
||||
CoreStoreDefaults.dataStack.addStorage(storage, completion: completion)
|
||||
}
|
||||
|
||||
/**
|
||||
Migrates a local storage to match the `CoreStoreDefaults.dataStack`'s managed object model version. This method does NOT add the migrated store to the data stack.
|
||||
|
||||
@@ -114,30 +114,4 @@ extension CoreStore {
|
||||
|
||||
return try CoreStoreDefaults.dataStack.addStorageAndWait(storage)
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a `CloudStorage` to the `CoreStoreDefaults.dataStack` and blocks until completion.
|
||||
```
|
||||
guard let storage = ICloudStore(
|
||||
ubiquitousContentName: "MyAppCloudData",
|
||||
ubiquitousContentTransactionLogsSubdirectory: "logs/config1",
|
||||
ubiquitousContainerID: "iCloud.com.mycompany.myapp.containername",
|
||||
ubiquitousPeerToken: "9614d658014f4151a95d8048fb717cf0",
|
||||
configuration: "Config1",
|
||||
cloudStorageOptions: .recreateLocalStoreOnModelMismatch
|
||||
) else {
|
||||
// iCloud is not available on the device
|
||||
return
|
||||
}
|
||||
try CoreStore.addStorageAndWait(storage)
|
||||
```
|
||||
- parameter storage: the local storage
|
||||
- throws: a `CoreStoreError` value indicating the failure
|
||||
- returns: the cloud storage added to the stack. Note that this may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
|
||||
*/
|
||||
@discardableResult
|
||||
public static func addStorageAndWait<T: CloudStorage>(_ storage: T) throws -> T {
|
||||
|
||||
return try CoreStoreDefaults.dataStack.addStorageAndWait(storage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,142 +248,6 @@ extension DataStack {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchronously adds a `CloudStorage` to the stack. Migrations are also initiated by default.
|
||||
```
|
||||
guard let storage = ICloudStore(
|
||||
ubiquitousContentName: "MyAppCloudData",
|
||||
ubiquitousContentTransactionLogsSubdirectory: "logs/config1",
|
||||
ubiquitousContainerID: "iCloud.com.mycompany.myapp.containername",
|
||||
ubiquitousPeerToken: "9614d658014f4151a95d8048fb717cf0",
|
||||
configuration: "Config1",
|
||||
cloudStorageOptions: .recreateLocalStoreOnModelMismatch
|
||||
) else {
|
||||
// iCloud is not available on the device
|
||||
return
|
||||
}
|
||||
dataStack.addStorage(
|
||||
storage,
|
||||
completion: { result in
|
||||
switch result {
|
||||
case .success(let storage): // ...
|
||||
case .failure(let error): // ...
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
- parameter storage: the cloud storage
|
||||
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `CloudStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
|
||||
*/
|
||||
public func addStorage<T: CloudStorage>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
|
||||
|
||||
let cacheFileURL = storage.cacheFileURL
|
||||
self.coordinator.performSynchronously {
|
||||
|
||||
if let _ = self.persistentStoreForStorage(storage) {
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
||||
completion(.success(storage))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if let persistentStore = self.coordinator.persistentStore(for: cacheFileURL as URL) {
|
||||
|
||||
if let existingStorage = persistentStore.storageInterface as? T,
|
||||
storage.matchesPersistentStore(persistentStore) {
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
||||
completion(.success(existingStorage))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let error = CoreStoreError.differentStorageExistsAtURL(existingPersistentStoreURL: cacheFileURL)
|
||||
Internals.log(
|
||||
error,
|
||||
"Failed to add \(Internals.typeName(storage)) at \"\(cacheFileURL)\" because a different \(Internals.typeName(NSPersistentStore.self)) at that URL already exists."
|
||||
)
|
||||
DispatchQueue.main.async {
|
||||
|
||||
completion(.failure(error))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
var cloudStorageOptions = storage.cloudStorageOptions
|
||||
cloudStorageOptions.remove(.recreateLocalStoreOnModelMismatch)
|
||||
|
||||
let storeOptions = storage.dictionary(forOptions: cloudStorageOptions)
|
||||
do {
|
||||
|
||||
_ = try self.createPersistentStoreFromStorage(
|
||||
storage,
|
||||
finalURL: cacheFileURL,
|
||||
finalStoreOptions: storeOptions
|
||||
)
|
||||
DispatchQueue.main.async {
|
||||
|
||||
completion(.success(storage))
|
||||
}
|
||||
}
|
||||
catch let error as NSError where storage.cloudStorageOptions.contains(.recreateLocalStoreOnModelMismatch) && error.isCoreDataMigrationError {
|
||||
|
||||
let finalStoreOptions = storage.dictionary(forOptions: storage.cloudStorageOptions)
|
||||
let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
|
||||
ofType: type(of: storage).storeType,
|
||||
at: cacheFileURL,
|
||||
options: storeOptions
|
||||
)
|
||||
_ = try self.schemaHistory
|
||||
.schema(for: metadata)
|
||||
.flatMap({ try storage.cs_eraseStorageAndWait(soureModel: $0.rawModel()) })
|
||||
_ = try self.createPersistentStoreFromStorage(
|
||||
storage,
|
||||
finalURL: cacheFileURL,
|
||||
finalStoreOptions: finalStoreOptions
|
||||
)
|
||||
}
|
||||
}
|
||||
catch let error as NSError
|
||||
where error.code == NSFileReadNoSuchFileError && error.domain == NSCocoaErrorDomain {
|
||||
|
||||
do {
|
||||
|
||||
_ = try self.addStorageAndWait(storage)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
||||
completion(.success(storage))
|
||||
}
|
||||
}
|
||||
catch {
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
||||
completion(.failure(CoreStoreError(error)))
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
|
||||
let storeError = CoreStoreError(error)
|
||||
Internals.log(
|
||||
storeError,
|
||||
"Failed to load \(Internals.typeName(NSPersistentStore.self)) metadata."
|
||||
)
|
||||
DispatchQueue.main.async {
|
||||
|
||||
completion(.failure(storeError))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Migrates a local storage to match the `DataStack`'s managed object model version. This method does NOT add the migrated store to the data stack.
|
||||
|
||||
|
||||
@@ -370,99 +370,6 @@ public final class DataStack: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a `CloudStorage` to the stack and blocks until completion.
|
||||
```
|
||||
guard let storage = ICloudStore(
|
||||
ubiquitousContentName: "MyAppCloudData",
|
||||
ubiquitousContentTransactionLogsSubdirectory: "logs/config1",
|
||||
ubiquitousContainerID: "iCloud.com.mycompany.myapp.containername",
|
||||
ubiquitousPeerToken: "9614d658014f4151a95d8048fb717cf0",
|
||||
configuration: "Config1",
|
||||
cloudStorageOptions: .recreateLocalStoreOnModelMismatch
|
||||
) else {
|
||||
// iCloud is not available on the device
|
||||
return
|
||||
}
|
||||
try dataStack.addStorageAndWait(storage)
|
||||
```
|
||||
- parameter storage: the local storage
|
||||
- throws: a `CoreStoreError` value indicating the failure
|
||||
- returns: the cloud storage added to the stack. Note that this may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
|
||||
*/
|
||||
@discardableResult
|
||||
public func addStorageAndWait<T: CloudStorage>(_ storage: T) throws -> T {
|
||||
|
||||
return try self.coordinator.performSynchronously {
|
||||
|
||||
if let _ = self.persistentStoreForStorage(storage) {
|
||||
|
||||
return storage
|
||||
}
|
||||
|
||||
let cacheFileURL = storage.cacheFileURL
|
||||
if let persistentStore = self.coordinator.persistentStore(for: cacheFileURL as URL) {
|
||||
|
||||
if let existingStorage = persistentStore.storageInterface as? T,
|
||||
storage.matchesPersistentStore(persistentStore) {
|
||||
|
||||
return existingStorage
|
||||
}
|
||||
|
||||
let error = CoreStoreError.differentStorageExistsAtURL(existingPersistentStoreURL: cacheFileURL)
|
||||
Internals.log(
|
||||
error,
|
||||
"Failed to add \(Internals.typeName(storage)) at \"\(cacheFileURL)\" because a different \(Internals.typeName(NSPersistentStore.self)) at that URL already exists."
|
||||
)
|
||||
throw error
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
var cloudStorageOptions = storage.cloudStorageOptions
|
||||
cloudStorageOptions.remove(.recreateLocalStoreOnModelMismatch)
|
||||
|
||||
let storeOptions = storage.dictionary(forOptions: cloudStorageOptions)
|
||||
do {
|
||||
|
||||
_ = try self.createPersistentStoreFromStorage(
|
||||
storage,
|
||||
finalURL: cacheFileURL,
|
||||
finalStoreOptions: storeOptions
|
||||
)
|
||||
return storage
|
||||
}
|
||||
catch let error as NSError where storage.cloudStorageOptions.contains(.recreateLocalStoreOnModelMismatch) && error.isCoreDataMigrationError {
|
||||
|
||||
let finalStoreOptions = storage.dictionary(forOptions: storage.cloudStorageOptions)
|
||||
let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
|
||||
ofType: type(of: storage).storeType,
|
||||
at: cacheFileURL,
|
||||
options: storeOptions
|
||||
)
|
||||
_ = try self.schemaHistory
|
||||
.schema(for: metadata)
|
||||
.flatMap({ try storage.cs_eraseStorageAndWait(soureModel: $0.rawModel()) })
|
||||
_ = try self.createPersistentStoreFromStorage(
|
||||
storage,
|
||||
finalURL: cacheFileURL,
|
||||
finalStoreOptions: finalStoreOptions
|
||||
)
|
||||
return storage
|
||||
}
|
||||
}
|
||||
catch {
|
||||
|
||||
let storeError = CoreStoreError(error)
|
||||
Internals.log(
|
||||
storeError,
|
||||
"Failed to add \(Internals.typeName(storage)) to the stack."
|
||||
)
|
||||
throw storeError
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: 3rd Party Utilities
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ extension DiffableDataSource {
|
||||
}
|
||||
```
|
||||
`DiffableDataSource.CollectionView` fully handles the reload animations.
|
||||
- SeeAlso: CoreStore's DiffableDataSource implementation is based on https://github.com/ra1028/DiffableDataSources
|
||||
*/
|
||||
open class CollectionView<O: DynamicObject>: NSObject, UICollectionViewDataSource {
|
||||
|
||||
@@ -217,7 +218,8 @@ extension DiffableDataSource {
|
||||
extension UICollectionView {
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
|
||||
// Implementation based on https://github.com/ra1028/DiffableDataSources
|
||||
@nonobjc
|
||||
fileprivate func reload<C, O>(
|
||||
using stagedChangeset: Internals.DiffableDataUIDispatcher<O>.StagedChangeset<C>,
|
||||
|
||||
@@ -59,6 +59,7 @@ extension DiffableDataSource {
|
||||
}
|
||||
```
|
||||
`DiffableDataSource.TableView` fully handles the reload animations. To turn change the default animation, set the `defaultRowAnimation`.
|
||||
- SeeAlso: CoreStore's DiffableDataSource implementation is based on https://github.com/ra1028/DiffableDataSources
|
||||
*/
|
||||
open class TableView<O: DynamicObject>: NSObject, UITableViewDataSource {
|
||||
|
||||
@@ -261,6 +262,7 @@ extension UITableView {
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
// Implementation based on https://github.com/ra1028/DiffableDataSources
|
||||
@nonobjc
|
||||
fileprivate func reload<C, O>(
|
||||
using stagedChangeset: Internals.DiffableDataUIDispatcher<O>.StagedChangeset<C>,
|
||||
@@ -282,6 +284,7 @@ extension UITableView {
|
||||
)
|
||||
}
|
||||
|
||||
// Implementation based on https://github.com/ra1028/DiffableDataSources
|
||||
@nonobjc
|
||||
fileprivate func reload<C, O>(
|
||||
using stagedChangeset: Internals.DiffableDataUIDispatcher<O>.StagedChangeset<C>,
|
||||
|
||||
@@ -34,6 +34,7 @@ extension Internals.DiffableDataUIDispatcher {
|
||||
|
||||
// MARK: - ChangeSet
|
||||
|
||||
// Implementation based on https://github.com/ra1028/DifferenceKit
|
||||
internal struct Changeset<C: Collection>: Equatable where C: Equatable {
|
||||
|
||||
var data: C
|
||||
|
||||
@@ -34,6 +34,7 @@ extension Internals.DiffableDataUIDispatcher {
|
||||
|
||||
// MARK: - DiffResult
|
||||
|
||||
// Implementation based on https://github.com/ra1028/DifferenceKit
|
||||
@usableFromInline
|
||||
internal struct DiffResult<Index> {
|
||||
|
||||
@@ -209,7 +210,8 @@ extension Internals.DiffableDataUIDispatcher {
|
||||
|
||||
|
||||
// MARK: - Trace
|
||||
|
||||
|
||||
// Implementation based on https://github.com/ra1028/DifferenceKit
|
||||
@usableFromInline
|
||||
internal struct Trace<Index> {
|
||||
|
||||
@@ -228,7 +230,8 @@ extension Internals.DiffableDataUIDispatcher {
|
||||
|
||||
|
||||
// MARK: - Occurrence
|
||||
|
||||
|
||||
// Implementation based on https://github.com/ra1028/DifferenceKit
|
||||
@usableFromInline
|
||||
internal enum Occurrence {
|
||||
|
||||
@@ -238,7 +241,8 @@ extension Internals.DiffableDataUIDispatcher {
|
||||
|
||||
|
||||
// MARK: - IndicesReference
|
||||
|
||||
|
||||
// Implementation based on https://github.com/ra1028/DifferenceKit
|
||||
@usableFromInline
|
||||
internal final class IndicesReference {
|
||||
|
||||
@@ -277,7 +281,8 @@ extension Internals.DiffableDataUIDispatcher {
|
||||
|
||||
|
||||
// MARK: - TableKey
|
||||
|
||||
|
||||
// Implementation based on https://github.com/ra1028/DifferenceKit
|
||||
@usableFromInline
|
||||
internal struct TableKey<T: Hashable>: Hashable {
|
||||
|
||||
|
||||
@@ -33,7 +33,8 @@ import Foundation
|
||||
extension Internals.DiffableDataUIDispatcher {
|
||||
|
||||
// MARK: - StagedChangeset
|
||||
|
||||
|
||||
// Implementation based on https://github.com/ra1028/DifferenceKit
|
||||
internal struct StagedChangeset<C: Collection>: ExpressibleByArrayLiteral, Equatable, RandomAccessCollection, RangeReplaceableCollection where C: Equatable {
|
||||
|
||||
@usableFromInline
|
||||
|
||||
@@ -142,38 +142,13 @@ extension Internals {
|
||||
@objc
|
||||
dynamic func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
|
||||
|
||||
switch type {
|
||||
|
||||
case .update,
|
||||
.move where indexPath == newIndexPath:
|
||||
let object = anObject as! NSManagedObject
|
||||
self.reloadedItemIDs.append(object.objectID)
|
||||
|
||||
case .insert,
|
||||
.delete,
|
||||
.move:
|
||||
return
|
||||
|
||||
@unknown default:
|
||||
return
|
||||
}
|
||||
let object = anObject as! NSManagedObject
|
||||
self.reloadedItemIDs.append(object.objectID)
|
||||
}
|
||||
|
||||
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
|
||||
|
||||
switch type {
|
||||
|
||||
case .update:
|
||||
self.reloadedSectionIDs.append(sectionInfo.name)
|
||||
|
||||
case .insert,
|
||||
.delete,
|
||||
.move:
|
||||
return
|
||||
|
||||
@unknown default:
|
||||
return
|
||||
}
|
||||
self.reloadedSectionIDs.append(sectionInfo.name)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -161,108 +161,3 @@ extension LocalStorage {
|
||||
&& persistentStore.url == self.fileURL
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - CloudStorageOptions
|
||||
|
||||
/**
|
||||
The `CloudStorageOptions` provides settings that tells the `DataStack` how to setup the persistent store for `LocalStorage` implementers.
|
||||
*/
|
||||
public struct CloudStorageOptions: OptionSet, ExpressibleByNilLiteral {
|
||||
|
||||
/**
|
||||
Tells the `DataStack` that the store should not be migrated or recreated, and should simply fail on model mismatch
|
||||
*/
|
||||
public static let none = CloudStorageOptions(rawValue: 0)
|
||||
|
||||
/**
|
||||
Tells the `DataStack` to delete and recreate the local store from the cloud store on model mismatch, otherwise exceptions will be thrown on failure instead
|
||||
*/
|
||||
public static let recreateLocalStoreOnModelMismatch = CloudStorageOptions(rawValue: 1 << 0)
|
||||
|
||||
/**
|
||||
Tells the `DataStack` to allow lightweight migration for the store when added synchronously
|
||||
*/
|
||||
public static let allowSynchronousLightweightMigration = CloudStorageOptions(rawValue: 1 << 2)
|
||||
|
||||
|
||||
// MARK: OptionSetType
|
||||
|
||||
public init(rawValue: Int) {
|
||||
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
|
||||
// MARK: RawRepresentable
|
||||
|
||||
public let rawValue: Int
|
||||
|
||||
|
||||
// MARK: ExpressibleByNilLiteral
|
||||
|
||||
public init(nilLiteral: ()) {
|
||||
|
||||
self.rawValue = 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - CloudStorage
|
||||
|
||||
/**
|
||||
The `CloudStorage` represents `StorageInterface`s that are synchronized from a cloud-based store.
|
||||
*/
|
||||
public protocol CloudStorage: StorageInterface {
|
||||
|
||||
/**
|
||||
The `NSURL` that points to the store file
|
||||
*/
|
||||
var cacheFileURL: URL { get }
|
||||
|
||||
/**
|
||||
Options that tell the `DataStack` how to setup the persistent store
|
||||
*/
|
||||
var cloudStorageOptions: CloudStorageOptions { get }
|
||||
|
||||
/**
|
||||
The options dictionary for the specified `CloudStorageOptions`
|
||||
*/
|
||||
func dictionary(forOptions options: CloudStorageOptions) -> [AnyHashable: Any]?
|
||||
|
||||
/**
|
||||
Called by the `DataStack` to perform actual deletion of the store file from disk. **Do not call directly!** The `sourceModel` argument is a hint for the existing store's model version. Implementers can use the `sourceModel` to perform necessary store operations. (Cloud stores for example, can set the NSPersistentStoreRemoveUbiquitousMetadataOption option before deleting)
|
||||
*/
|
||||
func cs_eraseStorageAndWait(soureModel: NSManagedObjectModel) throws
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Internal
|
||||
|
||||
extension CloudStorage {
|
||||
|
||||
internal func matchesPersistentStore(_ persistentStore: NSPersistentStore) -> Bool {
|
||||
|
||||
guard persistentStore.type == Self.storeType
|
||||
&& persistentStore.configurationName == (self.configuration ?? DataStack.defaultConfigurationName) else {
|
||||
|
||||
return false
|
||||
}
|
||||
guard persistentStore.url == self.cacheFileURL else {
|
||||
|
||||
return false
|
||||
}
|
||||
guard let persistentStoreOptions = persistentStore.options,
|
||||
let storeOptions = self.storeOptions else {
|
||||
|
||||
return persistentStore.options == nil && self.storeOptions == nil
|
||||
}
|
||||
return storeOptions.reduce(true) { (isMatch, tuple) in
|
||||
|
||||
let (key, value) = tuple
|
||||
let obj1 = persistentStoreOptions[key] as? NSObject
|
||||
let obj2 = value as? NSObject
|
||||
return isMatch && (obj1 == obj2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ extension DiffableDataSource {
|
||||
}
|
||||
```
|
||||
`DiffableDataSource.CollectionView` fully handles the reload animations.
|
||||
- SeeAlso: CoreStore's DiffableDataSource implementation is based on https://github.com/ra1028/DiffableDataSources
|
||||
*/
|
||||
open class CollectionView<O: DynamicObject>: NSObject, NSCollectionViewDataSource {
|
||||
|
||||
@@ -216,7 +217,8 @@ extension DiffableDataSource {
|
||||
extension NSCollectionView {
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
|
||||
// Implementation based on https://github.com/ra1028/DiffableDataSources
|
||||
@nonobjc
|
||||
fileprivate func reload<C, O>(
|
||||
using stagedChangeset: Internals.DiffableDataUIDispatcher<O>.StagedChangeset<C>,
|
||||
|
||||
Reference in New Issue
Block a user