首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UISearchDisplayController动画reloadData

UISearchDisplayController动画reloadData
EN

Stack Overflow用户
提问于 2013-02-10 19:27:30
回答 2查看 871关注 0票数 2

我已经阅读了所有关于UISearchDisplayController及其delegate的文档,但是我找不到任何方法来在搜索条件改变时使表视图具有动画效果。

我使用这两种方法:

它们都返回YES,但仍然找不到任何方法来做类似的事情:

我不知道这是否重要,但我正在使用NSfetchedResultsController变量来填充UISearchDisplayController中的UITableView

就这样了,谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-02-11 02:36:26

当搜索字符串或范围发生更改时,您将为获取的结果控制器分配一个新的fetch请求,因此必须调用performFetch来获取新的结果集。performFetch会重置控制器的状态,并且不会触发任何FRC委托方法。

因此,在更改获取请求之后,必须“手动”更新表视图。在大多数示例程序中,这是通过以下方式完成的

  • 在搜索表视图上调用reloadData,或
  • shouldReloadTableForSearchStringshouldReloadTableForSearchScope.

返回YES

效果是相同的:重新加载搜索表视图时不显示动画。

我不认为有任何内置/简单的方法可以在搜索谓词更改时动态地更新表视图。但是,您可以尝试以下方法(这只是一个想法,我自己并没有真正尝试过):

  • 在更改提取请求之前,请复制旧的结果集:

oldList=[将新的fetch请求copy];

  • Assign到FRC并调用performFetch.

  • Get NSArray新的结果集的fetchedResultsController fetchedObjects:

NSArray *newList = fetchedResultsController不调用搜索表view.

  • Compare oldListnewList上的fetchedResultsController reloadData来检测新的和已删除的对象。对于新对象调用insertRowsAtIndexPaths,对于删除的对象调用deleteRowsAtIndexPaths。这可以通过从parallel.

  • Return或shouldReloadTableForSearchScope.

遍历parallel.

  • Return NO中的两个列表来完成

正如我所说的,这只是一个想法,但我认为它可以工作。

票数 8
EN

Stack Overflow用户

发布于 2016-04-20 11:00:21

我知道这个问题很老了,但是我最近遇到了这个问题,我想要一个无论NSFetchedResultsController是如何初始化的都可以工作的解决方案。它基于@martin-r上面的答案。

下面是相应的要点:https://gist.github.com/stephanecopin/4ad7ed723f9857d96a777d0e7b45d676

代码语言:javascript
复制
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)
    }
}

它在NSFetchedResultsControllerpredicatesortDescriptors上公开了2个属性,这反映了在fetchRequest中找到的属性。

当设置了这些属性中的任何一个时,控制器将自动计算更改并通过委托发送更改,因此希望不会有重大的代码更改。如果你不想要动画,你仍然可以直接在fetchRequest上设置predicatesortDescriptors

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14797224

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档