2015-11-05 53 views
0

我正试图解决从CoreData提取数据比从Parse中检索数据并将其保存到CoreData之前执行更早的问题。我如何实现一个队列来执行从Parse提取数据?现在,当我启动应用程序时,数据库已更新,但tableView中未显示。GCD和核心数据

CoreData检索数据:

func fetchFromCoreData() { 

    do { 
     let results = try context.executeFetchRequest(fetchRequest) 

     medicines = results as! [Medicine] 
     print("FetchFromCoreData") 
     tableViewMedicines.reloadData() 

    } catch let error as NSError { 
     print("Could not fetch \(error), \(error.userInfo)") 
    } 

} 

读取数据从parse:

func fetchFromParse() { 

    let entity = NSEntityDescription.entityForName("Medicine", inManagedObjectContext: context) 
    let query = PFQuery(className: PFUser.currentUser()!.username!) 
    query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in 
     if error == nil { 
      for object in objects! { 

       if let name = object["medicineName"] as? String, 
        amount = object["amountQuantity"] as? String, 
        time = object["time"] as? String 
       { 

        let predicate = NSPredicate(format: "name = %@", name) 
        self.fetchRequest.predicate = predicate 

        do{ 
         let fetchedEntities = try self.context.executeFetchRequest(self.fetchRequest) as! [Medicine] 
         //save to Core Data 


         if fetchedEntities.count <= 0 { 
          let medicine = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: self.context) 
          medicine.setValue(name, forKey: "name") 
          medicine.setValue(amount, forKey: "amount") 
          medicine.setValue(time, forKey: "time") 

         } 

        } catch let error as NSError{ 
         print(error) 
        } 
       } 
      } 

     } 

      do { 

       try self.context.save() 
       print("Context.save") 


      } catch let error as NSError { 
       print("Could not save \(error), \(error.userInfo)") 
      } 
      self.fetchFromCoreData() 



    } 


} 

我打电话给他们viewWillAppear

override func viewWillAppear(animated: Bool) { 
    if Reachability.isConnectedToNetwork() { 
     //fetching data from Parse 

     fetchFromParse() 
     fetchFromCoreData() 

     tableViewMedicines.reloadData() 

    } else { 

     //fetching data from Core data 
     fetchFromCoreData() 
     logOutButton.enabled = false 

    } 
} 
+0

我编辑了我的帖子。我在viewWillAppear中调用它们,但不知道它有什么区别 – kiuzio2

+0

我不知道你会怎么做,但是你可能不得不调用'fetchFromCoreData'方法中的'fetchFromParse'方法,这样你就可以得到首先解析数据。您将测试网络连接,然后从解析中获取数据,否则您只会从磁盘获取数据。 –

+0

这可能是因为你的'findObjectsInBackground'回调将在未来的某个时刻被执行;在你重新加载你的表格数据之后。一个提示是重新考虑你调用tableViewMedicines.reloadData()的位置。 –

回答

0

这是发生,因为findObjectsInBackgroundWithBlock使得网络调用,并且只在以后执行它的块n,异步,一旦网络呼叫完成。你的代码执行顺序如下:

  1. 呼叫fetchFromParse()
  2. fetchFromParse(),调用解析。解析消失并在后台与网络通话...
  3. 致电fetchFromCoreData()
  4. 在稍后的某个时间点,Parse获得网络响应,并执行您的模块。

你应该想到的是异步网络调用将始终需要很长的时间,以及从网络活动的回调将总是被推迟到将来的某个未知的时间。意思是,你不能以某种方式移动列表中前面第4步。

GCD不是这里的答案。您必须等到网络活动完成后再处理Parse的结果。与此同时,你的应用需要有响应,所以你不能坐在等待发生。

您需要做的是在Parse调用完成后重新执行Core Data提取。如果您仍然显示早期抓取的结果,重新加载表视图是不够的。

+0

谢谢你解释整个过程。所以你建议把'fetchFromParse'放在'fetchFromParse'中的'query'块之后?我还有一个奇怪的问题,因为当我把'tableView.reloadData()'放在'fetchFromParse'中时,它只会在'tableView'中显示'CoreData'的一个调用。 – kiuzio2

+0

不,我建议在块内调用'fetchFromCoreData()',而不是在它之后调用。总的来说,该块将在稍后才会执行,并且只有在发生后才需要重新执行抓取。另外请注意,您可能不在块的主队列中,因此您可能需要使用'dispatch_async'来让Core Data和UI更新正常工作。 –