0

我对从 2 个不同原型单元格创建的 tableview 单元格有问题。我将自己的标签和图像添加到它们。

它们加载得很好,但是在我在表格视图中滚动,然后选择一个单元格后,来自其他单元格的标签被添加到单元格中已经存在的标签中。

我读过人们遇到的类似问题,但没有一个解决它只发生在选择时的事实。

我试过添加if (cell == nil){};,但没有效果。

cellForRowAtIndexPath的如下:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"NDSClassSubMenuViewController cellForRowAtIndexPath: running...");



    NDSClassAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    NSDictionary *childNodes = [appDelegate.children objectAtIndex:0];
    NSString *multicellstat = [childNodes objectForKey:@"@CELLTYPE"];
    NSLog(@"Multicellstat %@", multicellstat);
    NSLog(@"TESTING CHILD %@", childNodes);

    //ONLY LOADING SUB MENU OPTIONS
NSString *cellType;
    if (multicellstat == NULL){
        NSLog(@"cellForRowAtIndexPath: @CellType == multicell. Making multicell.");
        cellType = @"SegueCellSubmenu";
    }else {
        NSLog(@"cellForRowAtIndexPath: children variable is NOT NULL. Making MenuCell.");
        cellType = @"SegueCellMulti";

    }


    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellType forIndexPath:indexPath];

    if (multicellstat == NULL){
        NSLog(@"Not adding picture.");
    }else {


        dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        //this will start the image loading in bg
        dispatch_async(concurrentQueue, ^{

            UIView *blackBG = [[UIView alloc] initWithFrame:CGRectMake(5, 5, 60, 60)];
            blackBG.backgroundColor = [UIColor grayColor];

            NSURL *imageURL = [NSURL URLWithString:[childNodes objectForKey:@"@THUMBNAIL"]];
        NSData *data = [NSData dataWithContentsOfURL:imageURL];
        UIImage *image = [UIImage imageWithData:data];

        UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
        imageView.frame = CGRectMake(0, 0, 60, 60);
            int borderWidth = 1;
            imageView.frame = CGRectMake(borderWidth, borderWidth, blackBG.frame.size.width-borderWidth*2, blackBG.frame.size.height-borderWidth*2);


            dispatch_async(dispatch_get_main_queue(), ^{

                [cell addSubview:blackBG];
                [blackBG addSubview:imageView];


         });
        });


    }


    //NSDictionary *tweet = [[[[appDelegate.menuItems objectForKey:@"Table"] objectForKey:@"Parent"]objectAtIndex:indexPath.row] objectForKey:@"Child"];
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(70, 10, 210, 30)];
    UILabel *detailText = [[UILabel alloc] initWithFrame:CGRectMake(70, 35, 210, 30)];

    [cell.contentView addSubview:label];
    [cell.contentView addSubview:detailText];


    NSString *text = [[appDelegate.children objectAtIndex:indexPath.row] objectForKey:@"@MENUDESC"];
    NSString *name = [[appDelegate.children objectAtIndex:indexPath.row] objectForKey:@"@MENUDESC"];
    //NSLog(@"cellForRowAtIndexPath MENU ITEMS %@", text);

    //Title label
    label.text = NULL;
    label.text = text;
    [label setFont: [UIFont fontWithName:@"Arial" size:16.0]];

//Detail label
    detailText.text = NULL;
    detailText.text = name;
    [detailText setFont: [UIFont fontWithName:@"Arial" size:12.0]];
    //detailText.textColor = [UIColor colorWithRed:186.0/255.0 green:186.0/255.0 blue:186.0/255.0 alpha:1];
    detailText.textColor = [UIColor grayColor];

    //cell.textLabel.text = text;
    //cell.detailTextLabel.text = [NSString stringWithFormat:@"by %@", name];


    NSLog(@"Creating submenu item: %@", text);
     NSLog(@"NDSClassSubMenuViewController: cellForRowAtIndexPath: finished.");



    return cell;

}

任何人都知道我该如何解决这个问题?

4

2 回答 2

1

关键问题是运行 synch 的代码不应假定在图像请求完成后它正在修改的单元格与图像请求开始时是同一单元格(在相同的 indexPath 处)。

正确的配方是这样的:

  1. 如果我们有一个缓存结果,则使用缓存结果(因此我们不会在每次滚动时都进行 Web 请求),否则发出异步请求。
  2. 当请求完成时,缓存结果
  3. 使用原始 indexPath 来确定单元格是否仍然可见。如果是,请重新加载该 indexPath。新缓存的结果现在将在 cellForRowAtIndexPath 中可用。

这是一段代码,描述了如何在异步请求后正确更新表。在您的 cellForRowAtIndexPath 中,在调用此之前检查缓存的响应:

// in cellForRowAtIndexPath:
NSString *urlString = [childNodes objectForKey:@"@THUMBNAIL"]
NSURL *imageURL = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:imageURL];
NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
if (!cachedResponse) { 
    // we don't find this image/request in the cache, call asynch load
    [self asynchLoad:urlString forIndexPath:indexPath];
} else {
   // we got this image already, update the cell
    UIImage *image = [UIImage imageWithData:cachedResponse.data];
    // set the cell's UIImageView subview image to image
}

这里我们在 urlString 处加载图像,缓存结果,然后在请求完成后如果仍然可见,则在加载后重新加载 indexPath:

- (void)asynchLoad:(NSString *)urlString forIndexPath:(NSIndexPath *)indexPath {

    NSURL *imageURL = [NSURL URLWithString:[childNodes objectForKey:@"@THUMBNAIL"]];
    NSURLRequest *request = [NSURLRequest requestWithURL:imageURL];

    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        if (!error) {

            // cache the response
            NSCachedURLResponse *cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response data:data];
            [[NSURLCache sharedURLCache] storeCachedResponse:cachedResponse forRequest:self];

            // important part - we make no assumption about the state of the table at this point
            // find out if our original index path is visible, then update it, taking 
            // advantage of the cached image (and a bonus option row animation)

            NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
            if ([visiblePaths containsObject:indexPath]) {
                NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
                [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation: UITableViewRowAnimationFade];
                // because we cached the image, cellForRow... will see it and run fast
            }
        }
    }];
}
于 2013-03-10T16:51:32.593 回答
0

我通过创建自己的自定义单元类并使用情节提要设置布局来解决问题。

于 2013-03-12T13:07:13.817 回答