removed long-standing workaround for NSFetchedResultsController bugs since they seem to be fixed

This commit is contained in:
John Estropia
2018-12-18 18:43:36 +09:00
parent 5febf2542d
commit 4a28a39df6
5 changed files with 143 additions and 163 deletions

View File

@@ -86,10 +86,6 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
return
}
self.deletedSections = []
self.insertedSections = []
self.handler?.controllerWillChangeContent(controller)
}
@@ -104,7 +100,6 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
return
}
self.handler?.controllerDidChangeContent(controller)
}
@@ -115,98 +110,11 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
return
}
guard var actualType = NSFetchedResultsChangeType(rawValue: type.rawValue) else {
// This fix is for a bug where iOS passes 0 for NSFetchedResultsChangeType, but this is not a valid enum case.
// Swift will then always execute the first case of the switch causing strange behaviour.
// https://forums.developer.apple.com/thread/12184#31850
return
}
// This whole dance is a workaround for a nasty bug introduced in XCode 7 targeted at iOS 8 devices
// http://stackoverflow.com/questions/31383760/ios-9-attempt-to-delete-and-reload-the-same-index-path/31384014#31384014
// https://forums.developer.apple.com/message/9998#9998
// https://forums.developer.apple.com/message/31849#31849
if #available(iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
// I don't know if iOS 10 even attempted to fix this mess...
if case .update = actualType,
indexPath != nil,
newIndexPath != nil {
actualType = .move
}
}
switch actualType {
case .update:
guard let section = indexPath?[0] else {
return
}
if self.deletedSections.contains(section)
|| self.insertedSections.contains(section) {
return
}
case .move:
guard let indexPath = indexPath, let newIndexPath = newIndexPath else {
return
}
guard indexPath == newIndexPath else {
break
}
if self.insertedSections.contains(indexPath[0]) {
// Observers that handle the .Move change are advised to delete then reinsert the object instead of just moving. This is especially true when indexPath and newIndexPath are equal. For example, calling tableView.moveRowAtIndexPath(_:toIndexPath) when both indexPaths are the same will crash the tableView.
self.handler?.controller(
controller,
didChangeObject: anObject,
atIndexPath: indexPath,
forChangeType: .move,
newIndexPath: newIndexPath
)
return
}
if self.deletedSections.contains(indexPath[0]) {
self.handler?.controller(
controller,
didChangeObject: anObject,
atIndexPath: nil,
forChangeType: .insert,
newIndexPath: indexPath
)
return
}
guard #available(iOS 9.0, tvOS 9.0, watchOS 3.0, *) else {
return
}
self.handler?.controller(
controller,
didChangeObject: anObject,
atIndexPath: indexPath,
forChangeType: .update,
newIndexPath: nil
)
return
default:
break
}
self.handler?.controller(
controller,
didChangeObject: anObject,
atIndexPath: indexPath,
forChangeType: actualType,
forChangeType: type,
newIndexPath: newIndexPath
)
}
@@ -218,14 +126,6 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
return
}
switch type {
case .delete: self.deletedSections.insert(sectionIndex)
case .insert: self.insertedSections.insert(sectionIndex)
default: break
}
self.handler?.controller(
controller,
didChangeSection: sectionInfo,
@@ -242,13 +142,4 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
sectionIndexTitleForSectionName: sectionName
)
}
// MARK: Private
@nonobjc
private var deletedSections = Set<Int>()
@nonobjc
private var insertedSections = Set<Int>()
}