0

也许有人有大型核心数据库的工作经验(我在我的基础中有32k行,我需要向用户展示所有这些基础并在其中进行一些搜索),当我尝试读取基地到我fetchedResultsController我有3-5秒的延迟,我该如何解决这个问题? 我可以在一些后台线程中读取这个基地吗? 或者如果我通过关系将部分零件分离出来,对它有帮助吗? 我尝试在viewDidAppear通过fetchedResultsController在核心数据中处理大型基数

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与浅,所以我的主视图e是开得)我用下面的代码

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

其中i称为更新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!) 
} 
+0

你可以编辑你的问题来添加你创建读取结果控制器的代码吗?如何配置它可能是一个关键细节。添加了 –

+0

,并且还使用NSFetcherResultControllerDelegate方法更新tableView数据(controllerWillChangeContent,controllerDidChangeContent和didChangeObject)。我在“茶壶”的答案中添加了代码,但加载时间仍然是几秒钟 – Skie

回答

1

这里的一些准则:

  1. 使用批处理。将您的获取请求的fetchBatchSize设置为50returnsObjectsAsFaultsNO之类的内容。
  2. 在表格视图中使用估计高度。 estimatedRowHeight-tableView:estimatedHeightForRowAtIndexPath:UITableViewDelegate都可以。

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

+0

谢谢,基地的工作现在更好,但基地连接时仍然有一些加载时间,是真正的解决这个问题还是它是需要连接fetchedResultsController中的基础的时间? – Skie

+1

@Skie通过执行后台获取请求并将NSManagedObjectIDs传递给主线程(可能在应用程序启动后),您可以预热NSPersistentStoreCoordinator的缓存。 – bteapot

1

这不是因为你有32k条记录。这并不大。问题是,你显然是试图使用字符串属性的记录进行排序:

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

由一个字符串值排序32K的记录是大量的工作。这将需要时间。有几种可能的加速:

  1. 如果可能,按数字或日期属性而不是字符串进行排序。这是很多更快。如果你的数据没有一个有用的数字属性,也许你可以创建一个,这会给你相同的排序结果。
  2. 通过检查模型编辑器中的“索引”框来告知核心数据以索引此属性。这将有所帮助,但不如对数字属性进行排序。
+0

谢谢,我为我的“cardName”添加了“索引”,现在所有的基础都很快排序。我有一个新问题。我有更新一些谓词过滤在这个基地从其他viewController和第一个过滤器加载大约10秒,但是当我使用这个和/或新的谓词过滤次要我只有1秒延迟重新编码的搜索结果。为什么发生这种情况?也许我在内存中调用新的基础(我试图捕捉这个,但我不调用任何新的NSFetchRequestControllers)或者它不是更新fetchedResultsController的好方法? – Skie