在后台和tableView.reloadData()中获取Core Data对象

时间:2016-12-29 14:24:58

标签: ios swift core-data swift3

我想在后台加载Core Data对象,完成后应重新加载TableView。下面的代码给出了一个空tableView:

class ViewController: UIViewController {
 var fetchRequest: NSFetchRequest<Venue>!
 var venue:[Venue] = []
 var coreDataStack: CoreDataStack!

 override func viewDidLoad() {
      super.viewDidLoad()
      fetchRequest = Venue.fetchRequest()
      coreDataStack.storeContainer.performBackgroundTask {(context) in
           do {
                self.venue = try context.fetch(self.fetchRequesrt)
           } catch {
           }
           DispatchQueue.main.async {
                self.tableView.reloadData()
           }
      }
}

但是如果我们在上面没有chunk的viewDidLoad()中编写代码,那么一切正常,tableView就会填充数据:

venue = try! coreDataStack.managedContext.fetch(fetchRequesrt)
tableView.reloadData()

上面的代码有什么问题? 对于建议,我将非常感激!

编辑。这是正确的解决方案:

class ViewController: UIViewController {
 var fetchRequest: NSFetchRequest<Venue>!
 var venue:[Venue] = []
 var coreDataStack: CoreDataStack!

 override func viewDidLoad() {
   super.viewDidLoad()
   fetchRequest = Venue.fetchRequest()
   coreDataStack.storeContainer.performBackgroundTask {(context) in
   do {
    let venue = try context.fetch(self.fetchRequesrt)
    venue.map {$0.objectID}.forEach{self.venue.append(self.coreDataStack.managedContext.object(with: $0) as! Venue)}
    DispatchQueue.main.async {
     self.tableView.reloadData()
    }
   } catch {
   ...
   }
  }
  }
}

使用NSAsynchronousFetchRequest类的另一个解决方案。上面的例子如下所示:

class ViewController: UIViewController {
  var fetchRequesrt: NSFetchRequest<Venue>!
  var venue:[Venue] = []
  var asyncFetchRequest: NSAsynchronousFetchRequest<Venue>!
  var coreDataStack: CoreDataStack!
  fetchRequest = Venue.fetchRequest()
  override func viewDidLoad() {
    super.viewDidLoad()
   asyncFetchRequest = NSAsynchronousFetchRequest(fetchRequest:fetchRequest, completionBlock: { [unowned self] 
   (result: NSAsynchronousFetchResult) in
  guard let venue = result.finalResult else { return }
   self.venue = venue
   self.tableView.reloadData()
   })
   do {
     try coreDataStack.managedContext.execute(asyncFetchRequest)
     } catch {
      ...
     }
    }
   }

1 个答案:

答案 0 :(得分:2)

每当与Core Data和NSFetchedResultController进行交互时,您都应该使用TableView。它比您自己获取数据更加稳定和优化。

我对你的代码感到很困惑,我从来没有见过像这样的解决方案。也许你应该使用闭包函数和完成后调用reloadData,或者把整个块放到beginUpdates这样:

    self.tableView.beginUpdates()
coreDataStack.storeContainer.performBackgroundTask {(context) in
           do {
                self.venue = try context.fetch(self.fetchRequesrt)
           } catch {/*error goes here*/}
      }
self.tableView.endUpdates()

无论如何,我强烈建议您使用NSFetchedResultsController,因为它更容易执行backgroundTasks。