【问题标题】:Fetching Core Data object in the background and tableView.reloadData()在后台和 tableView.reloadData() 中获取核心数据对象
【发布时间】:2016-12-29 14:24:58
【问题描述】:

我想在后台加载 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()
           }
      }
}

但是如果我们在 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 {
      ...
     }
    }
   }

【问题讨论】:

    标签: ios swift core-data swift3


    【解决方案1】:

    在与 Core Data 和 TableView 本身交互时,您应该使用 NSFetchedResultController。它比您自己获取数据更加稳定和优化。

    我对您的代码感到非常困惑,我从未见过这样的解决方案。也许您应该使用闭包和完成调用 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,因为它更容易执行后台任务。

    【讨论】:

      猜你喜欢
      • 2010-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多