0

也许有人有使用大型核心数据库的经验(我的基础中有 32k 行,我需要向用户展示所有这些基础并在其中进行一些搜索),当我尝试读取基础时到我的 fetchedResultsController 我有 3-5 秒的延迟,我该如何解决这个问题?我可以在一些后台线程中阅读这个基础吗?或者如果我通过关系在某些部分上分开我的基础是否有帮助?我尝试在 viewDidAppear 中加载我的基地

    override func viewDidAppear(_ animated: Bool) {
        DispatchQueue.main.async {
            self.connectFetchedRequest()
            self.tableView.reloadData()
            self.indicatorLoad.stopAnimating()
        }
    }

    func connectFetchedRequest() {
        do {
            try self.fetchedResultsController.performFetch()
        }catch {
            print(error)
        }
    }

对于在基中搜索,我使用 UISearchBarDelegate 方法(但在向 searchText 添加字符时我仍然有一些“滞后”)

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        block?.cancel()
        block = DispatchWorkItem {
            let predicate = NSPredicate(format: "cardName contains[c] %@", searchText)
            self.fetchedResultsController.fetchRequest.predicate = predicate
            self.connectFetchedRequest()
            DispatchQueue.main.async(execute: {
                self.tableView.reloadData()
            })
        }
        DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 0.5, execute: block!)
    }

我使用以下代码创建了 fetchedResultsController

    lazy var context: NSManagedObjectContext = {
        let appDelegate = (UIApplication.shared.delegate as? AppDelegate)
        return appDelegate!.managedObjectContext
    }()

    lazy var fetchedResultsController: NSFetchedResultsController<CardsBaseClass> = {
        let fetchRequest = NSFetchRequest<CardsBaseClass>(entityName: "CardsBase")
        let sortDescriptor = NSSortDescriptor(key: "cardName", ascending: true)
        fetchRequest.sortDescriptors = [sortDescriptor]

        fetchRequest.fetchBatchSize = 50
        fetchRequest.returnsObjectsAsFaults = false

        let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.context, sectionNameKeyPath: nil, cacheName: nil)
        fetchedResultsController.delegate = self
        return fetchedResultsController
    }()

为了从其他 viewController 添加新的谓词(我打开 .overFullScreen 所以我的主视图与 base 也是打开的)我使用以下代码

predicateArrayClass.addPredicate(predicate: predicateType)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateTableViewByNewPredicate"), object: nil, userInfo: nil)
self.dismiss(animated: true, completion: nil)

我在哪里调用了更新 fetchResultController func

func updateTableViewByNewPredicate() {
        searchController.searchBar.text! = ""
        let predicateArray = predicateArrayClass.arrayOfPredicates
        block = DispatchWorkItem {
            self.fetchedResultsController.fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicateArray)
            self.connectFetchedRequest()
            DispatchQueue.main.async(execute: {
                self.tableView.reloadData()
            })
        }
        DispatchQueue.global(qos: .background).async(execute: block!)
}
4

2 回答 2

1

以下是一些指导方针:

  1. 使用批处理。将fetchBatchSize您的获取请求设置为50, 和.returnsObjectsAsFaultsNO
  2. 在表格视图中使用估计的高度。要么estimatedRowHeight-tableView:estimatedHeightForRowAtIndexPath:UITableViewDelegate做。

这将防止在每次重新加载时加载内存中的所有 32K 记录。

于 2016-11-15T09:38:56.023 回答
1

这不是因为你有 32k 条记录。那不是很大。问题是您显然是在尝试使用字符串属性对这些记录进行排序:

let sortDescriptor = NSSortDescriptor(key: "cardName", ascending: true)

按字符串值对 32k 条记录进行排序需要做很多工作。这需要时间。有几种加速它的可能性:

  1. 如果可能,请按数字或日期属性而不是字符串进行排序。这快得多。如果您的数据没有有用的数字属性,也许您可​​以制作一个可以为您提供相同排序结果的数据。
  2. 通过选中模型编辑器中的“索引”框,告诉 Core Data 索引这个属性。这会有所帮助,但不如对数字属性进行排序。
于 2016-11-15T21:03:43.743 回答