             
             return
         }
+
+        if #available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *) {}
+        else {
+
+            self.deletedSections = []
+            self.insertedSections = []
+        }
+        
         self.handler?.controllerWillChangeContent(controller)
     }
     

            
            return
        }
        self.handler?.controllerDidChangeContent(controller)
    }
    

            
            return
        }

        if #available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *) {

            self.handler?.controller(
                controller,
                didChangeObject: anObject,
                atIndexPath: indexPath,
                forChangeType: type,
                newIndexPath: newIndexPath
            )
            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 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
            }
            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,
            newIndexPath: newIndexPath
        )
    }
