正确加载tableview单元格数据的正确方法

pvl*_*spk 0 iphone objective-c uitableview ios

我尝试异步设置UITableViewCell'description'字段,但由于重用视图单元格,我在快速滚动我的tableview时遇到问题 - tableview单元格刷新了几次.我的代码如下.这有什么不对?

   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
    {
        [TimeExecutionTracker startTrackingWithName:@"cellForRowAtIndexPath"];

        static NSString *CellIdentifier = @"MessageCell";

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

        CTCoreMessage *message = [_searchResults objectAtIndex:indexPath.row];
        UILabel *fromLabel = (UILabel *)[cell viewWithTag:101];
        UILabel *dateLabel = (UILabel *)[cell viewWithTag:102];
        UILabel *subjectLabel = (UILabel *)[cell viewWithTag:103];
        UILabel *descriptionLabel = (UILabel *)[cell viewWithTag:104];
        [subjectLabel setText:message.subject];
        [fromLabel setText:[message.from toStringSeparatingByComma]];
        [dateLabel setText:[NSDateFormatter localizedStringFromDate:message.senderDate
                                                          dateStyle:NSDateFormatterShortStyle
                                                          timeStyle:nil]];


        NSString *cellHash = [[NSString stringWithFormat:@"%@%@%@",fromLabel.text,dateLabel.text,subjectLabel.text] md5];

        if([_tableViewDescirptions valueForKey:cellHash] == nil){

            [descriptionLabel setText:@"Loading ..."];

            dispatch_async(backgroundQueue, ^{

                BOOL isHTML;
                NSString *shortBody = [message bodyPreferringPlainText:&isHTML];
                shortBody = [shortBody substringToIndex: MIN(100, [shortBody length])];
                [_tableViewDescirptions setValue:shortBody forKey:cellHash];

                dispatch_async(dispatch_get_main_queue(), ^{

                    [descriptionLabel setText:[_tableViewDescirptions valueForKey:cellHash]];

                });
            });
        }else{

            [descriptionLabel setText:[_tableViewDescirptions valueForKey:cellHash]];
        }


        [TimeExecutionTracker stopTrackingAndPrint];

        return cell;
    }
Run Code Online (Sandbox Code Playgroud)

Mar*_*n R 5

dispatch_async(dispatch_get_main_queue(), ^{
    [descriptionLabel setText:[_tableViewDescirptions valueForKey:cellHash]];
});
Run Code Online (Sandbox Code Playgroud)

捕获当前值,descriptionLabel因此,当块执行时,即使该单元在此期间已被重用于不同的索引路径,也会更新该标签.

因此,您应该捕获单元格,并检查单元格(当前)索引路径是否仍然等于原始(捕获)索引路径.

您还应该_tableViewDescirptions仅在主线程上更新,因为它用作数据源.

这大致看起来像(不是编译器测试):

dispatch_async(dispatch_get_main_queue(), ^{
    [_tableViewDescirptions setValue:shortBody forKey:cellHash];
    if ([[tableView indexPathForCell:cell] isEqual:indexPath]) {
        UILabel *descriptionLabel = (UILabel *)[cell viewWithTag:104];
        [descriptionLabel setText:[_tableViewDescirptions valueForKey:cellHash]];
    }
});
Run Code Online (Sandbox Code Playgroud)

附注:获取/设置字典值的主要方法是objectForKeysetObject:forKey:. valueForKey:并且setValue:forKey:仅用于键值编码魔术.