麻烦异步下载UITableView

时间:2011-05-01 23:44:52

标签: objective-c asynchronous uitableview nsurlconnection nsurlrequest

我正在尝试异步下载UITableViewCell的图像,但它目前正在为每个单元格设置相同的图像。

请告诉我代码的问题:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }

    SearchObject *so = (SearchObject *)[_tableData objectAtIndex:indexPath.row];
    cell.textLabel.text = [[[[so tweet] stringByReplacingOccurrencesOfString:@"&quot;" withString:@"\""] stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"] stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"];
    cell.detailTextLabel.text = [so fromUser];
    if (cell.imageView.image == nil) {
        NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:[so userProfileImageURL]]];
        NSURLConnection *conn = [NSURLConnection connectionWithRequest:req delegate:self];
        [conn start];
    }
    if ([_cellImages count] > indexPath.row) {
        cell.imageView.image = [UIImage imageWithData:[_cellImages objectAtIndex:indexPath.row]];
    }
    return cell;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [_cellData appendData:data];
    [_cellImages addObject:_cellData];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.tableView reloadData];
}

2 个答案:

答案 0 :(得分:1)

您将从下载到同一数据对象的每个图像中追加数据。因此,在最好的情况下,数据对象最终会得到图像#1的数据,紧接着是图像#2的数据,依此类推;图像解码器显然是在数据块中取第一个图像并忽略后面的垃圾。您似乎也不知道NSURLConnections'connection:didReceiveData:不一定按照连接启动的顺序调用,connection:didReceiveData:每个连接可以被调用零次或多次(如果您的图像可能会被调用)超过几个kibibytes),并且不保证按顺序为表中的每个单元调用tableView:cellForRowAtIndexPath:。所有这些都将完全搞砸你的_cellImages阵列。

要做到这一点,你需要为每个连接都有一个单独的NSMutableData实例,你只需要将它添加到_cellImages数组中一次,并将其添加到行的正确索引而不是任意下一个可用指数。然后在connection:didReceiveData:中你需要找出要附加的正确的NSMutableData实例;这可以通过使用连接对象(使用valueWithNonretainedObject:包装在NSValue中)作为NSMutableDictionary中的键,或使用objc_setAssociatedObject将数据对象附加到连接对象,或者通过自己创建为您处理NSURLConnection的所有管理的类,并在完成时将数据对象交给您。

答案 1 :(得分:0)

我不知道这是否会导致问题,但在connection:didReceiveData:方法中,您只是将图像数据附加到数组中;你应该以这样一种方式存储图像数据,你可以将它链接到它应该显示的单元格。一种方法是使用NSMutableArray填充一堆[NSNull] s,然后在连接完成加载时替换适当索引处的null值。

此外,当连接尚未完成加载时,您将_cellData附加到_cellImages数组,您应该只使用connection:didFinishLoading方法执行此操作。