2013-04-04 140 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次,然后每次你滚动它时被调用的次数是您可以在屏幕上看到许多行/单元格