UISearchDisplayController animate reloadData

I read all the documentation about UISearchDisplayControllerand its delegate, but I can not find a way to animate the presentation of the table when changing the search criteria.

I use these two methods: UISearchDisplayController methods

They both return YES, but still cannot find a way to do something similar: UITableView Methods

I don’t know if this is important, but I use NSfetchedResultsControllerto fill UITableViewinUISearchDisplayController

Thank you!

+2
source share
2 answers

, performFetch, . performFetch - FRC.

, "".

  • reloadData
  • YES shouldReloadTableForSearchString shouldReloadTableForSearchScope.

: .

, - / . , ( , ):

  • :

    NSArray *oldList = [[fetchedResultsController fetchedObjects] copy];
    
  • FRC performFetch.

  • :

    NSArray *newList = [fetchedResultsController fetchedObjects];
    
  • reloadData .

  • oldList newList . insertRowsAtIndexPaths deleteRowsAtIndexPaths . .
  • NO shouldReloadTableForSearchString shouldReloadTableForSearchScope.

, , , .

+8

, , , , NSFetchedResultsController. @martin-r .

: https://gist.github.com/stephanecopin/4ad7ed723f9857d96a777d0e7b45d676

import CoreData

extension NSFetchedResultsController {
    var predicate: NSPredicate? {
        get {
            return self.fetchRequest.predicate
        }
        set {
            try! self.setPredicate(newValue)
        }
    }

    var sortDescriptors: [NSSortDescriptor]? {
        get {
            return self.fetchRequest.sortDescriptors
        }
        set {
            try! self.setSortDescriptors(newValue)
        }
    }

    func setPredicate(predicate: NSPredicate?) throws {
        try self.setPredicate(predicate, sortDescriptors: self.sortDescriptors)
    }

    func setSortDescriptors(sortDescriptors: [NSSortDescriptor]?) throws {
        try self.setPredicate(self.predicate, sortDescriptors: sortDescriptors)
    }

    func setPredicate(predicate: NSPredicate?, sortDescriptors: [NSSortDescriptor]?) throws {
        func updateProperties() throws {
            if let cacheName = cacheName {
                NSFetchedResultsController.deleteCacheWithName(cacheName)
            }

            self.fetchRequest.predicate = predicate
            self.fetchRequest.sortDescriptors = sortDescriptors
            try self.performFetch()
        }

        guard let delegate = self.delegate else {
            try updateProperties()
            return
        }

        let previousSections = self.sections ?? []
        let previousSectionsCount = previousSections.count
        var previousObjects = Set(self.fetchedObjects as? [NSManagedObject] ?? [])
        var previousIndexPaths: [NSManagedObject: NSIndexPath] = [:]
        previousObjects.forEach {
            previousIndexPaths[$0] = self.indexPathForObject($0)
        }
        try updateProperties()
        let newSections = self.sections ?? []
        let newSectionsCount = newSections.count
        var newObjects = Set(self.fetchedObjects as? [NSManagedObject] ?? [])
        var newIndexPaths: [NSManagedObject: NSIndexPath] = [:]
        newObjects.forEach {
            newIndexPaths[$0] = self.indexPathForObject($0)
        }

        let updatedObjects = newObjects.intersect(previousObjects)
        previousObjects.subtractInPlace(updatedObjects)
        newObjects.subtractInPlace(updatedObjects)

        var moves: [(object: NSManagedObject, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)] = []
        updatedObjects.forEach { updatedObject in
            if let previousIndexPath = previousIndexPaths[updatedObject],
                let newIndexPath = newIndexPaths[updatedObject]
            {
                if previousIndexPath != newIndexPath {
                    moves.append((updatedObject, previousIndexPath, newIndexPath))
                }
            }
        }

        if moves.isEmpty && previousObjects.isEmpty && newObjects.isEmpty {
            // Nothing really changed
            return
        }

        delegate.controllerWillChangeContent?(self)

        moves.forEach {
            delegate.controller?(self, didChangeObject: $0.object, atIndexPath: $0.fromIndexPath, forChangeType: .Move, newIndexPath: $0.toIndexPath)
        }

        let sectionDifference = newSectionsCount - previousSectionsCount
        if sectionDifference < 0 {
            (newSectionsCount..<previousSectionsCount).forEach {
                delegate.controller?(self, didChangeSection: previousSections[$0], atIndex: $0, forChangeType: .Delete)
            }
        } else if sectionDifference > 0 {
            (previousSectionsCount..<newSectionsCount).forEach {
                delegate.controller?(self, didChangeSection: newSections[$0], atIndex: $0, forChangeType: .Insert)
            }
        }

        previousObjects.forEach {
            delegate.controller?(self, didChangeObject: $0, atIndexPath: previousIndexPaths[$0], forChangeType: .Delete, newIndexPath: nil)
        }
        newObjects.forEach {
            delegate.controller?(self, didChangeObject: $0, atIndexPath: nil, forChangeType: .Insert, newIndexPath: newIndexPaths[$0])
        }

        delegate.controllerDidChangeContent?(self)
    }
}

2 NSFetchedResultsController, predicate sortDescriptors, , fetchRequest.
, , , , . , - predicate sortDescriptors fetchRequest.

+1

All Articles