add "updatedItemIdentifiers" utility to ListSnapshot

This commit is contained in:
John Estropia
2019-12-02 10:52:36 +09:00
parent b12dba4d15
commit 6f275eb63a
4 changed files with 24 additions and 55 deletions

View File

@@ -583,10 +583,10 @@
B5A992201EA898720091A2E3 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A9921E1EA898710091A2E3 /* UserInfo.swift */; }; B5A992201EA898720091A2E3 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A9921E1EA898710091A2E3 /* UserInfo.swift */; };
B5A992211EA898720091A2E3 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A9921E1EA898710091A2E3 /* UserInfo.swift */; }; B5A992211EA898720091A2E3 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A9921E1EA898710091A2E3 /* UserInfo.swift */; };
B5A992221EA898720091A2E3 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A9921E1EA898710091A2E3 /* UserInfo.swift */; }; B5A992221EA898720091A2E3 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A9921E1EA898710091A2E3 /* UserInfo.swift */; };
B5AA37F1235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AA37F0235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift */; }; B5AA37F1235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AA37F0235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift */; };
B5AA37F2235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AA37F0235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift */; }; B5AA37F2235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AA37F0235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift */; };
B5AA37F3235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AA37F0235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift */; }; B5AA37F3235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AA37F0235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift */; };
B5AA37F4235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AA37F0235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift */; }; B5AA37F4235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AA37F0235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift */; };
B5AA37FD235C3D1A00FFD4B9 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5AA37FC235C3D1A00FFD4B9 /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; B5AA37FD235C3D1A00FFD4B9 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5AA37FC235C3D1A00FFD4B9 /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
B5AEFAB51C9962AE00AD137F /* CoreStoreBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */; }; B5AEFAB51C9962AE00AD137F /* CoreStoreBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */; };
B5AEFAB61C9962AE00AD137F /* CoreStoreBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */; }; B5AEFAB61C9962AE00AD137F /* CoreStoreBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */; };
@@ -1014,7 +1014,7 @@
B5A80DF52212C1BC006096AA /* Playground_iOS.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Playground_iOS.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; B5A80DF52212C1BC006096AA /* Playground_iOS.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Playground_iOS.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionLock.swift; sourceTree = "<group>"; }; B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionLock.swift; sourceTree = "<group>"; };
B5A9921E1EA898710091A2E3 /* UserInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserInfo.swift; sourceTree = "<group>"; }; B5A9921E1EA898710091A2E3 /* UserInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserInfo.swift; sourceTree = "<group>"; };
B5AA37F0235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "diffableDataSource.CollectionView-AppKit.swift"; sourceTree = "<group>"; }; B5AA37F0235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiffableDataSource.CollectionView-AppKit.swift"; sourceTree = "<group>"; };
B5AA37FA235C3D1300FFD4B9 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS6.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; B5AA37FA235C3D1300FFD4B9 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS6.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
B5AA37FC235C3D1A00FFD4B9 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS6.0.sdk/System/Library/Frameworks/SwiftUI.framework; sourceTree = DEVELOPER_DIR; }; B5AA37FC235C3D1A00FFD4B9 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS6.0.sdk/System/Library/Frameworks/SwiftUI.framework; sourceTree = DEVELOPER_DIR; };
B5AD60CD1C90141E00F2B2E8 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; }; B5AD60CD1C90141E00F2B2E8 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; };
@@ -1609,7 +1609,7 @@
B5BF7FB1234C97910070E741 /* DiffableDataSource.swift */, B5BF7FB1234C97910070E741 /* DiffableDataSource.swift */,
B5BF7FB6234C97CE0070E741 /* DiffableDataSource.TableView-UIKit.swift */, B5BF7FB6234C97CE0070E741 /* DiffableDataSource.TableView-UIKit.swift */,
B5635D132356C39500B80E6B /* DiffableDataSource.CollectionView-UIKit.swift */, B5635D132356C39500B80E6B /* DiffableDataSource.CollectionView-UIKit.swift */,
B5AA37F0235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift */, B5AA37F0235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift */,
); );
name = DataSources; name = DataSources;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -2121,7 +2121,7 @@
B5A261211B64BFDB006EB6D3 /* MigrationType.swift in Sources */, B5A261211B64BFDB006EB6D3 /* MigrationType.swift in Sources */,
B53FBA0B1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */, B53FBA0B1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */,
B5E84F141AFF847B0064E85B /* DataStack+Querying.swift in Sources */, B5E84F141AFF847B0064E85B /* DataStack+Querying.swift in Sources */,
B5AA37F1235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift in Sources */, B5AA37F1235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift in Sources */,
B5D7A5B61CA3BF8F005C752B /* CSInto.swift in Sources */, B5D7A5B61CA3BF8F005C752B /* CSInto.swift in Sources */,
B56007141B3F6C2800A9A8F9 /* SectionBy.swift in Sources */, B56007141B3F6C2800A9A8F9 /* SectionBy.swift in Sources */,
B5DE522B230BD7CC00A22534 /* Internals.swift in Sources */, B5DE522B230BD7CC00A22534 /* Internals.swift in Sources */,
@@ -2474,7 +2474,7 @@
B52F743E1E9B8724005F3DAC /* DynamicSchema.swift in Sources */, B52F743E1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
18166884232B9ED00097C275 /* KeyPath+KeyPaths.swift in Sources */, 18166884232B9ED00097C275 /* KeyPath+KeyPaths.swift in Sources */,
B5E8A72121C1015300EF006A /* CoreStoreObject+Observing.swift in Sources */, B5E8A72121C1015300EF006A /* CoreStoreObject+Observing.swift in Sources */,
B5AA37F2235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift in Sources */, B5AA37F2235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift in Sources */,
B50E175D2351848E004F033C /* Internals.DiffableDataUIDispatcher.DiffResult.swift in Sources */, B50E175D2351848E004F033C /* Internals.DiffableDataUIDispatcher.DiffResult.swift in Sources */,
B5474D162227C08700B21FEC /* Internals.CoreStoreFetchRequest.swift in Sources */, B5474D162227C08700B21FEC /* Internals.CoreStoreFetchRequest.swift in Sources */,
B501322B2346A9AE00FC238B /* ListPublisher.swift in Sources */, B501322B2346A9AE00FC238B /* ListPublisher.swift in Sources */,
@@ -2698,7 +2698,7 @@
B52F74401E9B8724005F3DAC /* DynamicSchema.swift in Sources */, B52F74401E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
18166886232B9ED20097C275 /* KeyPath+KeyPaths.swift in Sources */, 18166886232B9ED20097C275 /* KeyPath+KeyPaths.swift in Sources */,
B5E8A72321C1015300EF006A /* CoreStoreObject+Observing.swift in Sources */, B5E8A72321C1015300EF006A /* CoreStoreObject+Observing.swift in Sources */,
B5AA37F4235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift in Sources */, B5AA37F4235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift in Sources */,
B50E175F2351848E004F033C /* Internals.DiffableDataUIDispatcher.DiffResult.swift in Sources */, B50E175F2351848E004F033C /* Internals.DiffableDataUIDispatcher.DiffResult.swift in Sources */,
B5474D182227C08700B21FEC /* Internals.CoreStoreFetchRequest.swift in Sources */, B5474D182227C08700B21FEC /* Internals.CoreStoreFetchRequest.swift in Sources */,
B501322E2346A9B100FC238B /* ListPublisher.swift in Sources */, B501322E2346A9B100FC238B /* ListPublisher.swift in Sources */,
@@ -2922,7 +2922,7 @@
B52F743F1E9B8724005F3DAC /* DynamicSchema.swift in Sources */, B52F743F1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
18166885232B9ED10097C275 /* KeyPath+KeyPaths.swift in Sources */, 18166885232B9ED10097C275 /* KeyPath+KeyPaths.swift in Sources */,
B5E8A72221C1015300EF006A /* CoreStoreObject+Observing.swift in Sources */, B5E8A72221C1015300EF006A /* CoreStoreObject+Observing.swift in Sources */,
B5AA37F3235C28EE00FFD4B9 /* diffableDataSource.CollectionView-AppKit.swift in Sources */, B5AA37F3235C28EE00FFD4B9 /* DiffableDataSource.CollectionView-AppKit.swift in Sources */,
B50E175E2351848E004F033C /* Internals.DiffableDataUIDispatcher.DiffResult.swift in Sources */, B50E175E2351848E004F033C /* Internals.DiffableDataUIDispatcher.DiffResult.swift in Sources */,
B5474D172227C08700B21FEC /* Internals.CoreStoreFetchRequest.swift in Sources */, B5474D172227C08700B21FEC /* Internals.CoreStoreFetchRequest.swift in Sources */,
B501322D2346A9B000FC238B /* ListPublisher.swift in Sources */, B501322D2346A9B000FC238B /* ListPublisher.swift in Sources */,

View File

@@ -96,6 +96,11 @@ extension Internals {
return self.structure.allItemIDs return self.structure.allItemIDs
} }
var updatedItemIdentifiers: Set<NSManagedObjectID> {
return self.structure.reloadedItems
}
func numberOfItems(inSection identifier: String) -> Int { func numberOfItems(inSection identifier: String) -> Int {
return self.itemIdentifiers(inSection: identifier).count return self.itemIdentifiers(inSection: identifier).count
@@ -121,16 +126,6 @@ extension Internals {
return self.structure.allSectionIDs.firstIndex(of: identifier) return self.structure.allSectionIDs.firstIndex(of: identifier)
} }
func isReloaded(sectionID: String) -> Bool? {
return self.structure.isReloaded(sectionID: sectionID)
}
func isReloaded(itemID: NSManagedObjectID) -> Bool? {
return self.structure.isReloaded(itemID: itemID)
}
mutating func appendItems(_ identifiers: [NSManagedObjectID], toSection sectionIdentifier: String?) { mutating func appendItems(_ identifiers: [NSManagedObjectID], toSection sectionIdentifier: String?) {
self.structure.append(itemIDs: identifiers, to: sectionIdentifier) self.structure.append(itemIDs: identifiers, to: sectionIdentifier)
@@ -282,10 +277,12 @@ extension Internals {
// MARK: Internal // MARK: Internal
var sections: [Section] var sections: [Section]
private(set) var reloadedItems: Set<NSManagedObjectID>
init() { init() {
self.sections = [] self.sections = []
self.reloadedItems = []
} }
init(sections: [NSFetchedResultsSectionInfo], fetchOffset: Int, fetchLimit: Int?) { init(sections: [NSFetchedResultsSectionInfo], fetchOffset: Int, fetchLimit: Int?) {
@@ -327,6 +324,7 @@ extension Internals {
) )
} }
self.sections = newSections self.sections = newSections
self.reloadedItems = []
} }
var allSectionIDs: [String] { var allSectionIDs: [String] {
@@ -339,24 +337,6 @@ extension Internals {
return self.sections.lazy.flatMap({ $0.elements }).map({ $0.differenceIdentifier }) return self.sections.lazy.flatMap({ $0.elements }).map({ $0.differenceIdentifier })
} }
func isReloaded(sectionID: String) -> Bool? {
return self.sections.first(where: { $0.differenceIdentifier == sectionID })?.isReloaded
}
func isReloaded(itemID: NSManagedObjectID) -> Bool? {
for section in self.sections {
guard let item = section.elements.first(where: { $0.differenceIdentifier == itemID }) else {
return nil
}
return item.isReloaded
}
return nil
}
func items(in sectionID: String) -> [NSManagedObjectID] { func items(in sectionID: String) -> [NSManagedObjectID] {
guard let sectionIndex = self.sectionIndex(of: sectionID) else { guard let sectionIndex = self.sectionIndex(of: sectionID) else {
@@ -488,6 +468,7 @@ extension Internals {
mutating func update<S: Sequence>(itemIDs: S) where S.Element == NSManagedObjectID { mutating func update<S: Sequence>(itemIDs: S) where S.Element == NSManagedObjectID {
let itemPositionMap = self.itemPositionMap() let itemPositionMap = self.itemPositionMap()
var newItemIDs: Set<NSManagedObjectID> = []
for itemID in itemIDs { for itemID in itemIDs {
guard let itemPosition = itemPositionMap[itemID] else { guard let itemPosition = itemPositionMap[itemID] else {
@@ -496,7 +477,9 @@ extension Internals {
} }
self.sections[itemPosition.sectionIndex] self.sections[itemPosition.sectionIndex]
.elements[itemPosition.itemRelativeIndex].isReloaded = true .elements[itemPosition.itemRelativeIndex].isReloaded = true
newItemIDs.insert(itemID)
} }
self.reloadedItems.formUnion(newItemIDs)
} }
mutating func append(sectionIDs: [String]) { mutating func append(sectionIDs: [String]) {

View File

@@ -215,25 +215,11 @@ public struct ListSnapshot<O: DynamicObject>: RandomAccessCollection, Hashable {
} }
/** /**
Checks if the `ListSnapshot` has changes in the specified section. Returns item identifiers for updated objects. This is mainly useful for Data Source adapters such as `UICollectionViewDiffableDataSource` or `UITableViewDiffableDataSource` which work on collection diffs when reloading. Since objects with same IDs resolve as "equal" in their old and new states, adapters may need extra heuristics to determine which row items need reloading. If your row items are all observing changes from each corresponding `ObjectPublisher`, or if you are using CoreStore's built-in `DiffableDataSource`s, there is no need to inspect this property.
- parameter sectionID: the section identifier. Using an index outside the valid range will return `nil`.
- returns: `true` if the specified section has changes, `false` if no changes, or `nil` if the `sectionID` does not exist
*/ */
public func hasChanges(sectionID: String) -> Bool? { var updatedItemIdentifiers: Set<NSManagedObjectID> {
return self.diffableSnapshot.isReloaded(sectionID: sectionID) return self.diffableSnapshot.updatedItemIdentifiers
}
/**
Checks if the `ListSnapshot` has changes for the specified item.
- parameter itemID: the item identifier. Using an index outside the valid range will return `nil`.
- returns: `true` if the specified item has changes, `false` if no changes, or `nil` if the `itemID` does not exist
*/
public func hasChanges(itemID: NSManagedObjectID) -> Bool? {
return self.diffableSnapshot.isReloaded(itemID: itemID)
} }
/** /**