滚动后选择单元格标签文本

时间:2013-03-10 16:35:06

标签: objective-c scroll tableview cell

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

它们加载正常,但在我在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;

}

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

2 个答案:

答案 0 :(得分:1)

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

正确的食谱是这样的:

  1. 如果我们有一个缓存结果,则使用缓存结果(因此我们每次滚动时都不会执行Web请求),否则请进行异步请求。
  2. 请求完成后,缓存结果
  3. 使用原始indexPath确定单元格是否仍然可见。如果是,则重新加载indexPath。新缓存的结果现在将在cellForRowAtIndexPath中可用。
  4. 这是一段代码,描述了在异步请求之后如何在表中正确更新。在您的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
                }
            }
        }];
    }
    

答案 1 :(得分:0)

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