2016-02-11 26 views
1

我試圖等待解析異步功能斯威夫特重裝我的UITableView等待解析異步功能在斯威夫特

我不知道,如果完成處理程序中,這是非常有用完成案件。或調度異步。

我真的很困惑!有人可以幫助與此

var posts = [PFObject]() 
for post in posts { 
    post.fetchInBackground() 
} 
tableView.reloadData() // I want to execute that when the async functions have finished execution 

回答

2

你想使用fetchAllInBackground:Block我有問題在循環中啓動一堆解析調用,它將花費比預期的更長的時間來返回所有它們。 fetch documentation

它應該是這個樣子:

PFObject.fetchAllInBackground(posts, block: { (complete, error) in 
    if (error == nil && complete) { 
     self.tableView.reloadData() 
    } 
}) 

有一點要注意的是,在你的榜樣職位空和通用PFObject。我假設這只是爲了舉例。否則,如果你想獲得Parse中的所有文章(而不是更新當前的文章),你會想使用PFQuery而不是抓取。 query documentation

1

您需要使用fetchInBackgroundWithBlock。或者,如果您要等到所有已加載並更新UI,請使用PFObject的+fetchAllInBackground:block:。請注意,這是一種類方法,因此將被稱爲PFObject.fetchAllInBackground(...。請參閱文檔here

無論哪種方式,因爲您在後臺線程中運行,您必須更新主線程上的UI。這通常使用dispatch_async完成。

另一件需要注意的事情是,如果在循環中運行fetchInBackgroundWithBlock並收集數組中的所有結果,則數組不是線程安全的。您將不得不使用類似dispatch_barrier或您自己的同步隊列來同步對陣列的訪問。代碼的第二個選項是以下:

// Declared once and shared by each call (set your own name)... 
let queue = dispatch_queue_create("my.own.queue", nil) 

// For each call... 
dispatch_sync(queue) { 
    self.myArray.append(myElement) 
} 
+0

即使我用fetchInBackgroundWithBlock它不會幫助,只要我想所有的人要完成更新我的UI數據 –

+0

真的嗎?通常情況下,您逐漸更新用戶界面,因爲每一個加載。 – Michael

+0

我使用它的方式我不需要將'self.tableView.reloadData()'調度到主隊列。我從我的'viewDidLoad()'func調用'fetchData()',所以也許如果你從其他地方調用它,你需要發送'self.tableView.reloadData'到主隊列 – MikeG

0

下面是使用fetchInBackgroundWithBlock的一個例子完成後重新加載tableView

var myArray = [String]() 
func fetchData() { 
    let userQuery: PFQuery = PFUser.query()! 

    userQuery.findObjectsInBackgroundWithBlock({ 
     (users, error) -> Void in 

     var userData = users! 

     if error == nil { 
      if userData.count >= 1 { 
       for i in 0...users!.count-1 { 
        self.myArray.append(userData[i].valueForKey("dataColumnInParse") as! String) 
       } 
      } 
      self.tableView.reloadData() 
     } else { 
      print(error) 
     } 
    }) 
} 

我的例子是用戶類的查詢,但你的想法。 ..

+0

是否保證完成處理程序將在主線程上執行? – CouchDeveloper

+0

我不確定它是否有保證。 – MikeG

+0

如果完成處理程序在主線程之外的任何其他線程上執行,那麼您的解決方案可能會崩潰:表視圖嘗試訪問'self.myArray'以呈現單元,而同一個數組則由另一個線程修改。 – CouchDeveloper

1

這是我做,以幫助異步進程的協調少許類:

class CompletionBlock 
{ 
    var completionCode:()->() 

    init?(_ execute:()->()) 
    { completionCode = execute } 

    func deferred() {} 

    deinit 
    { completionCode() } 
} 

訣竅是用最後一個異步塊之後要執行的代碼創建CompletionBlock的實例,並對閉包內的對象進行引用。

let reloadTable = CompletionBlock({ self.tableView.reloadData() }) 
var posts = [PFObject]() 
for post in posts 
{ 
    post.fetchInBackground(){ reloadTable.deferred() } 
} 

直到最後捕獲超出範圍的對象將保持「活着」。然後,對象本身將超出範圍,其deinit將被稱爲執行您的終止代碼。

+0

這不起作用,沒有解決我的問題 –

0

我已經嘗試了一些塊,他們似乎在主線程中調用,這意味着可以在那裏進行任何UI更改。我已經習慣了測試的代碼看起來是這樣的:

func reloadPosts() { 
    PFObject.fetchAllIfNeededInBackground(posts) { 
    [unowned self] (result, error) in 

    if let err = error { 
     self.displayError(err) 
    } 

    self.tableView.reloadData() 
    } 
} 

如果你是在有關被稱爲主線程塊是否可以使用NSThread類檢查此

print(NSThread.currentThread().isMainThread) 
疑問

如果你希望它是防彈你可以用你的reloadDatadispatch_block_t以確保它是在主線程

編輯: 如果塊主線程上執行文檔沒有任何地方的狀態,但source code是很清楚,它確實

+ (void)fetchAllIfNeededInBackground:(NSArray *)objects block:(PFArrayResultBlock)block { 
    [[self fetchAllIfNeededInBackground:objects] thenCallBackOnMainThreadAsync:block]; 
}