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