如何在IIT的uitableview中使用可重用单元

use*_*564 9 uibutton uitableview ios

好.我似乎无法深入了解tableviews如何工作.有人请向我解释如何在表格视图中重复使用单元格,尤其是在滚动时?我对此有一个主要的痛点是,当我在一个单元格中创建一个动作时,其他单元格在滚动时会受到影响.我尝试使用一个数组作为模型的后端,但是当我没有想到时,我仍然会得到更改的单元格.要弄清楚的是,为什么当数组中的模型没有改变时它们会发生变化.

一个简单的例子:

表格视图单元格与"喜欢"按钮.当我单击其中一个单元格中的按钮时,按钮文本变为"不同"(到目前为止一直很好).但是当我向下滚动时,其他单元格也会显示"不同",即使我没有选择它们.当我向上滚动时,我最初选择的单元格会再次更改,而更新的单元格也会更改.

我似乎无法弄清楚这一点.如果你能告诉我一个有用的示例源代码,那就太棒了!谢谢!

- (void)viewDidLoad
{
    [super viewDidLoad];


    likeState = [[NSMutableArray alloc]init];

    int i =0;
    for (i=0; i<20; i++) {
        [likeState addObject:[NSNumber numberWithInt:0]];
    }
} 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [myButton setTitle:@"Like" forState:UIControlStateNormal];
    [myButton addTarget:self action:@selector(tapped:) forControlEvents:UIControlEventTouchUpInside];
    myButton.frame = CGRectMake(14.0, 10.0, 125.0, 25.0);
    myButton.tag =indexPath.row;
    [cell.contentView addSubview:myButton];

    if (cell ==nil) {


    }

    if ([[likeState objectAtIndex:indexPath.row]boolValue]==NO) {
        [myButton setTitle:@"Like" forState:UIControlStateNormal];

    }
    else{
        [myButton setTitle:@"Unlike" forState:UIControlStateNormal];


    }


    return cell;
}
-(void)tapped:(UIButton *)sender{

[likeState replaceObjectAtIndex:sender.tag withObject:[NSNumber numberWithInt:1]];

    [sender setTitle:@"Unlike" forState:UIControlStateNormal];

}
Run Code Online (Sandbox Code Playgroud)

sta*_*Man 12

我假设你这样做是Storyboard因为你还没有通过它创建你的按钮Interface Builder,你需要检查正在重复使用的单元格是否已经有了按钮.
根据您当前的逻辑,您将在单元格重新出现时创建一个新的按钮实例.

我建议如下:

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

    //following is required when using XIB but not needed when using Storyboard
    /*
     if (cell == nil) {
         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
     }
     */
    //Reason:
    //[1] When using XIB, dequeueReusableCellWithIdentifier does NOT create a cell so (cell == nil) condition occurs
    //[2] When using Storyboard, dequeueReusableCellWithIdentifier DOES create a cell and so (cell == nil) condition never occurs

    //check if cell is being reused by checking if the button already exists in it
    UIButton *myButton = (UIButton *)[cell.contentView viewWithTag:100];

    if (myButton == nil) {
        myButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [myButton setFrame:CGRectMake(14.0,10.0,125.0,25.0)];
        [myButton setTag:100]; //the tag is what helps in the first step
        [myButton setTitle:@"Like" forState:UIControlStateNormal];
        [myButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        [myButton addTarget:self action:@selector(tapped:andEvent:) forControlEvents:UIControlEventTouchUpInside];
        [cell.contentView addSubview:myButton];

        NSLog(@"Button created");
    }
    else {
        NSLog(@"Button already created");
    }

    if ([likeState[indexPath.row] boolValue]) {
        [myButton setTitle:@"Unlike" forState:UIControlStateNormal];
    }
    else {
        [myButton setTitle:@"Like" forState:UIControlStateNormal];
    }

    return cell;
}
Run Code Online (Sandbox Code Playgroud)
-(void)tapped:(UIButton *)sender andEvent:(UIEvent *)event
{
    //get index
    NSSet *touches = [event allTouches];
    UITouch *touch = [touches anyObject];
    CGPoint currentTouchPosition = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:currentTouchPosition];

    //toggle "like" status
    if ([likeState[indexPath.row] boolValue]) {
        [likeState replaceObjectAtIndex:indexPath.row withObject:@(0)];
        [sender setTitle:@"Like" forState:UIControlStateNormal];
    }
    else {
        [likeState replaceObjectAtIndex:indexPath.row withObject:@(1)];
        [sender setTitle:@"Unlike" forState:UIControlStateNormal];
    }
}
Run Code Online (Sandbox Code Playgroud)