2016-04-24 37 views
0

我想在Core Data中加載照片,但這需要一些後臺線程,所以發生這種情況時我的對象被保存在沒有其照片的Core Data中,我得到的照片是零。我的團隊的照片也是如此。在執行另一個塊之前執行所有後臺線程

簡而言之,在每次迭代中,我將一個對象保存在Core Data中,並且保存發生得比加載我的Photo數據更快。

我試過了Semaphors,障礙,羣體......但都沒有工作。我當然做錯了什麼,但我不知道是什麼。如果有人能夠幫助我,我會非常感激,已經有2個星期了,我正在爲這個問題而努力。這是我的一個簡化版本的代碼,完整版是可訪問以下:

// MARK - ViewDidLoad 
override func viewDidLoad() { 
    // This method is only called once, so you want to create any controls or arrays here 
    super.viewDidLoad() 

    // Verifying connectivity to internet 
    if Reachability.isConnectedToNetwork() == true { 

    // Getting data from Parse + getDataInBackgroundWithBlock 

    }else{ 

    } 
} 


// MARK - Action of the login button 
@IBAction func loginBtn_click(sender: AnyObject) { 
    if usernameTxt.text == "" || passwordTxt.text == "" { 
     self.displayAlert("Error", message: "Please enter a username and password") 
    }else{ 

     // MARK - Login the user 
     PFUser.logInWithUsernameInBackground(usernameTxt.text!, password: passwordTxt.text!) { (user, error) -> Void in 

      if error == nil { 

       let queue = dispatch_queue_create("com.karagan.app.queue", DISPATCH_QUEUE_CONCURRENT) 

       dispatch_async(queue, {() -> Void in 
        self.getObjectsFromQueryWithAscendingOrder("Add", key: "user", value: userName, ascendingOrder: "added", completionHandler: { (objects1) -> Void in 

       // Update of an array in background 

        }) 
       }) 



       dispatch_async(queue, {() -> Void in 

       // Update of an array in background 

       }) 



       dispatch_async(queue, {() -> Void in 
        self.getObjectsFromQueryWithAscendingOrder("Group", key: "membersUsername", value: userName, ascendingOrder: "membersUsername", completionHandler: { (objects3) -> Void in 

       // Update of an array in background 

         // MARK - Adding all the users in Core data 
         for var i = 0; i < usersFromParseDataBase.count; i++ { 

          let entity = NSEntityDescription.entityForName("Users", inManagedObjectContext: self.managedObjectContext) 
          let newUser = Users(entity: entity!, insertIntoManagedObjectContext: self.managedObjectContext) 
          if self.arrayAddedUsers.contains(usersFromParseDataBase[i].username){ 

       // Saving new records in Core Data     

          } 
         } 
        }) 
       }) 

       dispatch_async(queue, {() -> Void in 
        self.getObjectsFromQueryWithDescendingOrder("Group", key: "membersUsername", value: userName, descendingOrder: "conversationUpdate", completionHandler: { (objects4) -> Void in 

          if array.count == 2 { 

        // Getting data in background - photo.getDataInbackgroundWithBlock     

           } 
          }else{ 

       // Getting data in background - photo.getDataInbackgroundWithBlock 

          } 
         } 
        }) 
       }) 

       dispatch_barrier_async(queue, {() -> Void in 

     // Doing some stuff in background which needs the data from threads above 

       }) 

      }else{ 
       // Print error from loginWithUsernaemInBackground 
      } 
     } 
    } 
} 

這是被顯示到日誌,這樣你就可以清楚地看到,完成圖片的加載之前執行屏障被執行。

TEST 3 - interacting user has been saved to core data 
Loading profile image 
Loading profile image 
Loading group image 
Loading profile image 
Loading profile image 
9 
5 
Loading group image 
Loading group image 
Loading group image 
Loading group image 

事情是我以後需要這些數據用於其他操作。我的代碼不一致。

+1

您可能需要查看dispatch_group_create(),dispatch_group_wait()和dispatch_group_async()以獲得一組您希望在繼續之前完成的任務。此鏈接可能有所幫助:http://stackoverflow.com/questions/11909629/waiting-until-two-async-blocks-are-executed-before-starting-another-block –

+0

如果您正在調度的代碼塊是,他們自己,異步任務,你可能不得不明確地'dispatch_group_enter' /'leave'。如果沒有看到生成這些日誌消息的代碼,將很難診斷您的問題或進一步建議。或者,坦率地說,因爲你的代碼太複雜了,你可能想要構建[一個更簡單,可重現的例子](http://stackoverflow.com/help/mcve),它表現了你描述的那種錯誤。 – Rob

+0

Hello Rob,我添加了一個簡單版本的代碼,只有最重要的部分。它是否全面?如果沒有,我可以嘗試使其更簡單。謝謝你的幫助。迪茲,我已經嘗試dispatch_group_create()...但我仍然有同樣的問題。只是我不知道如何正確實施它。 我總是得到相同的問題,除非我添加「睡眠(Uint32)」到我的最後一個塊,但這是不一致的。 – C00kieMonsta

回答

-1

我認爲你是在正確的軌道上。當我創建一個簡單的程序,並使用dispatch_barrier_async它完美的作品:

let queue = dispatch_queue_create("com.karagan.app.queue", DISPATCH_QUEUE_CONCURRENT) 

dispatch_async(queue, {() -> Void in 
    sleep(1) 
    print("1") 
}) 

dispatch_async(queue, {() -> Void in 
    sleep(2) 
    print("2") 
}) 

dispatch_async(queue, {() -> Void in 
    sleep(3) 
    print("3") 
}) 

dispatch_async(queue, {() -> Void in 
    sleep(4) 
    print("4") 
}) 

dispatch_barrier_async(queue, {() -> Void in 
    print("done") 
}) 

輸出:

1 
2 
3 
4 
done 

我認爲這個問題是dispatch_async不等待調用PFFile.getDataInBackgroundWithBlock完成:

photoFile.getDataInBackgroundWithBlock({ (imageData, error) -> Void in 
    if error == nil { 
     self.arrayImageFiles.append(imageData!) 
     print("Loading group image") 
    } 
}) 

嘗試將所有呼叫切換到getDataInBackgroundWithBlock並同步呼叫到PFFile.getDatahttps://parse.com/docs/osx/api/Categories/PFFile%28Synchronous%29.html#/c:objc%28cs%29PFFile%28im%29getData :)改爲:

var imageData = photoFile.getData 
if (imageData != nil) { 
    self.arrayImageFiles.append(imageData!) 
} 

這應該不會有任何性能問題,因爲您已經在異步執行此代碼。

+0

感謝馬克的回答。我仍然需要做一些測試,但這可能對我有幫助。我不知道可以在主線程上加載圖像數據。我真的很感謝你的幫助,如果能真正解決我的問題,我會告訴你。 – C00kieMonsta

+0

如果以前提交給同一隊列的任務是_synchronous_,則只能將'dispatch_barrier_async' _can用作「標記」。但在OP中,它們是異步的。也就是說,調用返回_immediately_並且 - 對於隊列 - 此塊已完成。 – CouchDeveloper

+0

@CouchDeveloper這就是我在回答中說的,爲什麼我建議讓這些任務同步。我錯過了什麼嗎? – markwatsonatx

相關問題