2013-04-04 176 views
0

正在開發一個應用程序,我必須從JSON獲取數據並在UITableView中顯示。在後臺獲取數據。但它似乎無限循環。dispatch_async進入無限循環

任何幫助將不勝感激。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 

static NSString *CellIdentifier = @"Cell"; 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 
queue = dispatch_queue_create("com.events.app", NULL); 
dispatch_async(queue, ^{ 
    [self load]; 
    //Need to go back to the main thread since this is UI related 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // store the downloaded image in your model 
     Events *evObj = [eventsArray objectAtIndex:[indexPath row]]; 
     NSLog(@"evObj = %@",evObj); 
     cell.textLabel.text = evObj.eName; 
     cell.detailTextLabel.text = @"Detailed Text"; 
     [self.tableView beginUpdates]; 
     [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] 
           withRowAnimation:UITableViewRowAnimationLeft]; 
     [self.tableView endUpdates]; 
    }); 
}); 
    // Configure the cell... 



return cell; 
} 
+0

您不能在具有返回類型的方法中使用異步方法。由於'UITableViewCell'被重用,你可以修改一個不再綁定到相同索引路徑的單元。你也不應該在'tableView:cellForRowAtIndexPath:'中重新插入單元格,因爲這會調用'tableView:cellForRowAtIndexPath:'。 – rckoenes 2013-04-04 12:02:38

+2

@vitality這是不正確的,你應該在主線程上執行UI任務。當它們異步分派時,塊將被添加到主隊列並按順序執行。 – rckoenes 2013-04-04 12:06:59

+0

@rckoenes的確我不知道我的頭在剛纔的位置:P – 2013-04-04 12:09:13

回答

2

它進入循環,因爲發送-reloadRowsAtIndexPaths:withRowAnimation:將觸發UITableView要問您的數據源與-tableView:cellForRowAtIndexPath:

另一個細胞如果你想異步更新細胞,你必須更新直接的UI元素,但要避免重裝整個細胞。如果事情沒有自動更新,您可以在更新後發送-setNeedsDisplay-setNeedsLayout

+0

嗯....虐待這個嘗試。 thanx – LeXeR 2013-04-04 12:16:17

+0

嘿猜猜看.....它工作。這是reloadRowsAtIndexPaths導致它無限循環。 Thanx哥們。我喜歡SO – LeXeR 2013-04-04 12:20:37

+0

非常歡迎您! – svena 2013-04-04 12:22:13

1

只是刪除所有asynchronuos電話:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 

static NSString *CellIdentifier = @"Cell"; 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 

    if(cell == nil) { 
    /// load the cell. 
    } 


    // store the downloaded image in your model 
    Events *evObj = [eventsArray objectAtIndex:[indexPath row]]; 
    NSLog(@"evObj = %@",evObj); 
    cell.textLabel.text = evObj.eName; 
    cell.detailTextLabel.text = @"Detailed Text"; 


    return cell; 
} 

只需推動[self load];到你的代碼的其他部分,如viewDidLoad

+0

我試圖將其移動到viewdidload,但它不會更新numberofrowsinsection計數。 – LeXeR 2013-04-04 12:14:47

+1

加載後調用[table reloadData]。 – ArtFeel 2013-04-04 12:16:47

0

區分數據部分和UI部分。

I.e.

只需調用[self load];方法一次,或者多次您需要。最好的地方是viewDidLoad方法。

重新加載數據,並在UITableView的呈現他們可能看起來像這樣(有GCD)

dispatch_queue_t queue = dispatch_queue_create("com.events.app", NULL);

dispatch_async(queue, ^{ 
[self load]; 

//Need to go back to the main thread since this is UI related 
dispatch_async(dispatch_get_main_queue(), ^{ 
    [self.tableview reloadData]; 

//don't forget to release your queue 
dispatch_release(queue); 

}); 

})的實施;

複製從rckoenes - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {}方法的實施就大功告成了;)

但要記住一件重要的事情。你的第一個拋出的代碼會導致很大的開銷,每次調用這個方法時,你都要下載,解析和設置數據,至少在uitableview加載自己的時候開始3次,然後每次你滾動它時被調用的次數是您可以在屏幕上看到許多行/單元格