Skip to content

Commit

Permalink
Use System Diff (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
lickel authored Jul 13, 2021
1 parent e0344e6 commit 09196e1
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 267 deletions.
20 changes: 0 additions & 20 deletions FetchRequests.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
471C50A222C6D18D007F73E9 /* FetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509122C6D18D007F73E9 /* FetchedResultsController.swift */; };
471C50A422C6D18D007F73E9 /* FetchableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509322C6D18D007F73E9 /* FetchableObject.swift */; };
471C50A522C6D18D007F73E9 /* FetchableEntityID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509422C6D18D007F73E9 /* FetchableEntityID.swift */; };
471C50A722C6D18D007F73E9 /* simplediff.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509722C6D18D007F73E9 /* simplediff.swift */; };
471C50BC22C6D337007F73E9 /* FetchedResultsControllerTestHarness.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C50B022C6D337007F73E9 /* FetchedResultsControllerTestHarness.swift */; };
471C50BE22C6D337007F73E9 /* TestObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C50B222C6D337007F73E9 /* TestObject.swift */; };
471C50BF22C6D337007F73E9 /* FetchRequestAssociationTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C50B422C6D337007F73E9 /* FetchRequestAssociationTestCase.swift */; };
Expand All @@ -39,7 +38,6 @@
47A6ECD822CA8FA80034A854 /* FetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509122C6D18D007F73E9 /* FetchedResultsController.swift */; };
47A6ECD922CA8FA80034A854 /* PausableFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C508F22C6D18D007F73E9 /* PausableFetchedResultsController.swift */; };
47A6ECDA22CA8FA80034A854 /* CollectionType+SortDescriptors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C508B22C6D18D007F73E9 /* CollectionType+SortDescriptors.swift */; };
47A6ECDB22CA8FA80034A854 /* simplediff.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509722C6D18D007F73E9 /* simplediff.swift */; };
47A6ECDC22CA8FA80034A854 /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C508822C6D18D007F73E9 /* Logging.swift */; };
47A6ECDD22CA8FA80034A854 /* FetchableEntityID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509422C6D18D007F73E9 /* FetchableEntityID.swift */; };
47A6ECDE22CA8FA80034A854 /* FetchableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509322C6D18D007F73E9 /* FetchableObject.swift */; };
Expand All @@ -54,7 +52,6 @@
47A6ED0922CA905A0034A854 /* FetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509122C6D18D007F73E9 /* FetchedResultsController.swift */; };
47A6ED0A22CA905A0034A854 /* PausableFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C508F22C6D18D007F73E9 /* PausableFetchedResultsController.swift */; };
47A6ED0B22CA905A0034A854 /* CollectionType+SortDescriptors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C508B22C6D18D007F73E9 /* CollectionType+SortDescriptors.swift */; };
47A6ED0C22CA905A0034A854 /* simplediff.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509722C6D18D007F73E9 /* simplediff.swift */; };
47A6ED0D22CA905A0034A854 /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C508822C6D18D007F73E9 /* Logging.swift */; };
47A6ED0E22CA905A0034A854 /* FetchableEntityID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509422C6D18D007F73E9 /* FetchableEntityID.swift */; };
47A6ED0F22CA905A0034A854 /* FetchableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509322C6D18D007F73E9 /* FetchableObject.swift */; };
Expand All @@ -79,7 +76,6 @@
47A6ED3A22CA90A20034A854 /* FetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509122C6D18D007F73E9 /* FetchedResultsController.swift */; };
47A6ED3B22CA90A20034A854 /* PausableFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C508F22C6D18D007F73E9 /* PausableFetchedResultsController.swift */; };
47A6ED3C22CA90A20034A854 /* CollectionType+SortDescriptors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C508B22C6D18D007F73E9 /* CollectionType+SortDescriptors.swift */; };
47A6ED3D22CA90A20034A854 /* simplediff.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509722C6D18D007F73E9 /* simplediff.swift */; };
47A6ED3E22CA90A20034A854 /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C508822C6D18D007F73E9 /* Logging.swift */; };
47A6ED3F22CA90A20034A854 /* FetchableEntityID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509422C6D18D007F73E9 /* FetchableEntityID.swift */; };
47A6ED4022CA90A20034A854 /* FetchableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471C509322C6D18D007F73E9 /* FetchableObject.swift */; };
Expand Down Expand Up @@ -192,8 +188,6 @@
471C509122C6D18D007F73E9 /* FetchedResultsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchedResultsController.swift; sourceTree = "<group>"; };
471C509322C6D18D007F73E9 /* FetchableObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchableObject.swift; sourceTree = "<group>"; };
471C509422C6D18D007F73E9 /* FetchableEntityID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchableEntityID.swift; sourceTree = "<group>"; };
471C509622C6D18D007F73E9 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
471C509722C6D18D007F73E9 /* simplediff.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = simplediff.swift; sourceTree = "<group>"; };
471C50AC22C6D337007F73E9 /* CollapsibleSectionsFetchedResultsControllerTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollapsibleSectionsFetchedResultsControllerTestCase.swift; sourceTree = "<group>"; };
471C50AE22C6D337007F73E9 /* PausableFetchedResultsControllerTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PausableFetchedResultsControllerTestCase.swift; sourceTree = "<group>"; };
471C50AF22C6D337007F73E9 /* PaginatingFetchedResultsControllerTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaginatingFetchedResultsControllerTestCase.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -316,7 +310,6 @@
isa = PBXGroup;
children = (
471C506F22C6D0DB007F73E9 /* FetchRequests.h */,
471C509522C6D18D007F73E9 /* simplediff-swift */,
471C508622C6D18D007F73E9 /* Sources */,
471C507022C6D0DB007F73E9 /* Info.plist */,
);
Expand Down Expand Up @@ -355,15 +348,6 @@
path = Sources;
sourceTree = "<group>";
};
471C509522C6D18D007F73E9 /* simplediff-swift */ = {
isa = PBXGroup;
children = (
471C509622C6D18D007F73E9 /* LICENSE */,
471C509722C6D18D007F73E9 /* simplediff.swift */,
);
path = "simplediff-swift";
sourceTree = "<group>";
};
471C50A822C6D1D6007F73E9 /* Controller */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -751,7 +735,6 @@
471C50A022C6D18D007F73E9 /* PausableFetchedResultsController.swift in Sources */,
471C509C22C6D18D007F73E9 /* CollectionType+SortDescriptors.swift in Sources */,
6623972F267D034D009B696F /* FetchableRequest.swift in Sources */,
471C50A722C6D18D007F73E9 /* simplediff.swift in Sources */,
471C509922C6D18D007F73E9 /* Logging.swift in Sources */,
47D33F072334163100E247E4 /* JSON.swift in Sources */,
471C50A522C6D18D007F73E9 /* FetchableEntityID.swift in Sources */,
Expand Down Expand Up @@ -796,7 +779,6 @@
47A6ECD922CA8FA80034A854 /* PausableFetchedResultsController.swift in Sources */,
47A6ECDA22CA8FA80034A854 /* CollectionType+SortDescriptors.swift in Sources */,
66239732267D034D009B696F /* FetchableRequest.swift in Sources */,
47A6ECDB22CA8FA80034A854 /* simplediff.swift in Sources */,
47A6ECDC22CA8FA80034A854 /* Logging.swift in Sources */,
47D33F0A2334163100E247E4 /* JSON.swift in Sources */,
47A6ECDD22CA8FA80034A854 /* FetchableEntityID.swift in Sources */,
Expand All @@ -821,7 +803,6 @@
47A6ED0A22CA905A0034A854 /* PausableFetchedResultsController.swift in Sources */,
47A6ED0B22CA905A0034A854 /* CollectionType+SortDescriptors.swift in Sources */,
66239731267D034D009B696F /* FetchableRequest.swift in Sources */,
47A6ED0C22CA905A0034A854 /* simplediff.swift in Sources */,
47A6ED0D22CA905A0034A854 /* Logging.swift in Sources */,
47D33F092334163100E247E4 /* JSON.swift in Sources */,
47A6ED0E22CA905A0034A854 /* FetchableEntityID.swift in Sources */,
Expand Down Expand Up @@ -866,7 +847,6 @@
47A6ED3B22CA90A20034A854 /* PausableFetchedResultsController.swift in Sources */,
47A6ED3C22CA90A20034A854 /* CollectionType+SortDescriptors.swift in Sources */,
66239730267D034D009B696F /* FetchableRequest.swift in Sources */,
47A6ED3D22CA90A20034A854 /* simplediff.swift in Sources */,
47A6ED3E22CA90A20034A854 /* Logging.swift in Sources */,
47D33F082334163100E247E4 /* JSON.swift in Sources */,
47A6ED3F22CA90A20034A854 /* FetchableEntityID.swift in Sources */,
Expand Down
100 changes: 36 additions & 64 deletions FetchRequests/Sources/Controller/FetchedResultsController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -516,35 +516,15 @@ private extension FetchedResultsController {
objectsToInsert.removeAll()
}
performChanges(emitChanges: emitChanges) {
let operations = diff(fetchedObjects, objects)
let operations = objects.difference(from: fetchedObjects)

var index = fetchedObjects.endIndex
for operation in operations.reversed() {
switch operation.type {
case .insert:
break

case .noop:
index -= operation.elements.count

case .delete:
index -= operation.elements.count
remove(operation.elements, atIndex: index, emitChanges: emitChanges)
}
}

index = 0
for operation in operations {
switch operation.type {
case .insert:
insert(operation.elements, atIndex: index, emitChanges: emitChanges)
index += operation.elements.count

case .noop:
index += operation.elements.count
switch operation {
case let .remove(index, element, _):
remove(element, atIndex: index, emitChanges: emitChanges)

case .delete:
break
case let .insert(index, element, _):
insert(element, atIndex: index, emitChanges: emitChanges)
}
}
}
Expand Down Expand Up @@ -627,7 +607,7 @@ private extension FetchedResultsController {
continue
}
}
insert([object], atIndex: newFetchIndex, emitChanges: emitChanges)
insert(object, atIndex: newFetchIndex, emitChanges: emitChanges)
}
}

Expand Down Expand Up @@ -808,56 +788,48 @@ private extension FetchedResultsController {
}
}

func remove(_ objects: [FetchedObject], atIndex index: Int, emitChanges: Bool = true) {
for (arrayIndex, object) in objects.enumerated().reversed() {
let fetchIndex = index + arrayIndex

guard let indexPath = self.indexPath(forFetchIndex: fetchIndex) else {
return
}
func remove(_ object: FetchedObject, atIndex index: Int, emitChanges: Bool = true) {
guard let indexPath = self.indexPath(forFetchIndex: index) else {
return
}

stopObserving(object)
stopObserving(object)

fetchedObjects.remove(at: fetchIndex)
sections[indexPath.section].objects.remove(at: indexPath.item)
fetchedObjectIDs.remove(object.id)
fetchedObjects.remove(at: index)
sections[indexPath.section].objects.remove(at: indexPath.item)
fetchedObjectIDs.remove(object.id)

notifyDeleting(object, at: indexPath, emitChanges: emitChanges)
notifyDeleting(object, at: indexPath, emitChanges: emitChanges)

if sections[indexPath.section].objects.isEmpty {
let section = sections.remove(at: indexPath.section)
notifyDeleting(section, at: indexPath.section, emitChanges: emitChanges)
}
if sections[indexPath.section].objects.isEmpty {
let section = sections.remove(at: indexPath.section)
notifyDeleting(section, at: indexPath.section, emitChanges: emitChanges)
}
}

func insert(_ objects: [FetchedObject], atIndex index: Int, emitChanges: Bool = true) {
for (arrayIndex, object) in objects.enumerated() {
let fetchIndex = index + arrayIndex

let sectionName = object.sectionName(forKeyPath: sectionNameKeyPath)
let sectionIndex = idealSectionIndex(forSectionName: sectionName)
func insert(_ object: FetchedObject, atIndex index: Int, emitChanges: Bool = true) {
let sectionName = object.sectionName(forKeyPath: sectionNameKeyPath)
let sectionIndex = idealSectionIndex(forSectionName: sectionName)

let sectionPrefix = sections[0..<sectionIndex].reduce(0) { $0 + $1.numberOfObjects }
let sectionObjectIndex = fetchIndex - sectionPrefix
let sectionPrefix = sections[0..<sectionIndex].reduce(0) { $0 + $1.numberOfObjects }
let sectionObjectIndex = index - sectionPrefix

if sections.endIndex <= sectionIndex || sections[sectionIndex].name != sectionName {
assert(sectionObjectIndex == 0, "For some reason a section wasn't deleted")
let section = Section(name: sectionName)
sections.insert(section, at: sectionIndex)
if sections.endIndex <= sectionIndex || sections[sectionIndex].name != sectionName {
assert(sectionObjectIndex == 0, "For some reason a section wasn't deleted")
let section = Section(name: sectionName)
sections.insert(section, at: sectionIndex)

notifyInserting(section, at: sectionIndex, emitChanges: emitChanges)
}
notifyInserting(section, at: sectionIndex, emitChanges: emitChanges)
}

fetchedObjects.insert(object, at: fetchIndex)
sections[sectionIndex].objects.insert(object, at: sectionObjectIndex)
fetchedObjectIDs.insert(object.id)
fetchedObjects.insert(object, at: index)
sections[sectionIndex].objects.insert(object, at: sectionObjectIndex)
fetchedObjectIDs.insert(object.id)

let indexPath = IndexPath(item: sectionObjectIndex, section: sectionIndex)
notifyInserting(object, at: indexPath, emitChanges: emitChanges)
let indexPath = IndexPath(item: sectionObjectIndex, section: sectionIndex)
notifyInserting(object, at: indexPath, emitChanges: emitChanges)

startObserving(object)
}
startObserving(object)
}

func startObserving(_ object: FetchedObject) {
Expand Down
14 changes: 0 additions & 14 deletions FetchRequests/Tests/Models/LoggingTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,4 @@ class LoggingTestCase: XCTestCase {
CWLogWarning("Warning")
CWLogError("Error")
}

func testDiffDebug() {
let operationTypes: [OperationType] = [.insert, .delete, .noop]
let operationTypesStrings = operationTypes.map { $0.description }
XCTAssertEqual(operationTypesStrings, ["+", "-", "="])

let operations: [FetchRequests.Operation<Int>] = [
Operation(type: .insert, elements: [0]),
Operation(type: .delete, elements: [0]),
Operation(type: .noop, elements: [0]),
]
let operationsStrings = operations.map { $0.description }
XCTAssertEqual(operationsStrings, ["[+0]", "[-0]", "0"])
}
}
22 changes: 0 additions & 22 deletions FetchRequests/simplediff-swift/LICENSE

This file was deleted.

Loading

0 comments on commit 09196e1

Please sign in to comment.