Во-первых, вы должны положить в виду, что managedObjectContext работает на одном потоке. И вы должны получить доступ/отредактировать загруженные объекты в том же потоке.
В вашем случае вы будете взаимодействовать с объектами, которые вы собираетесь загрузить по основному потоку. Например, загруженные объекты базы данных заполнят tableView
, и это должно быть сделано в основном потоке. Это заставляет managedObjectContext быть MainContextType, который работает в основном потоке.
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html
Вы не должны бояться запуска NSFetchedResultsController на главном потоке, поскольку он загружает объекты в пакетном режиме. Однако вы не используете контроллер FetchedResults, как следует. Вы не должны иметь эти две строки в своем коде.
personalArray = fetchResultController.fetchedObjects!
self.tableView.reloadData()
Вы должны получить доступ к загруженному объекту, используя этот метод fetchResultController .objectAtIndexPath(indexPath)
.
Это пример того, как использовать NSFetchedResultsController
class ViewController: UITableViewController NSFetchedResultsControllerDelegate{
lazy var fetchedResultsController: NSFetchedResultsController = {
let fetchRequest = ... //Create the fetch request
let sortDescriptor = ... //Create a sortDescriptor
let predicate = ...//Create the predicate if you want to filter the results
fetchRequest.predicate = predicate
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: mainContext, sectionNameKeyPath: nil, cacheName: nil)
fetchedResultsController.delegate = self
return fetchedResultsController
}()
override fun viewDidLoad(){
super.viewDidLoad()
do {
try self.fetchedResultsController.performFetch()
}catch {
print(error)
}
}
func controllerWillChangeContent(controller: NSFetchedResultsController) {
tableView.beginUpdates()
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
tableView.endUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch (type) {
case .Insert:
if let indexPath = newIndexPath {
tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
break;
case .Delete:
if let indexPath = indexPath {
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
break;
case .Update:
if let indexPath = indexPath {
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
break;
case .Move:
if let indexPath = indexPath, newIndexPath = newIndexPath {
tableView.moveRowAtIndexPath(indexPath, toIndexPath: newIndexPath)
}
break;
}
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let sections = fetchedResultsController.sections {
let sectionInfo = sections[section]
return sectionInfo.numberOfObjects
}
return 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let obj = fetchedResultsController.objectAtIndexPath(indexPath){
....
}
}
спасибо, но если у меня есть 32k строк в основных данных (загрузка базы в NSFetchedResultsController занимает несколько секунд, и я хочу, чтобы добавить поиск в эта база), и мне нужно ускорить загрузку основных данных, что я должен делать? могу ли я добавить больше отношений к основным данным и попытаться загрузить базу через отношения по группам, или это тоже займет это время? – Skie
Это действительно зависит от того, что вы пытаетесь сделать ... Вы должны попытаться оптимизировать свои запросы. Используйте индексирование. Но включение NSFetchedresultscontroller в фоновый контекст - это кошмар, потому что он не предназначен для использования таким образом. – ELKA