好.我似乎不能很好地了解桌面视图的工作原理.有人可以向我解释细胞在桌面中是否重复使用,特别是滚动时?关于这一点的一个主要痛点是,当我在一个单元格中创建一个动作时,其他单元格会在滚动时受到影响.我尝试使用一个数组作为模型的后端,但是我仍然想到,当不考虑时,它会改变细胞.需要弄清楚的是,当阵列中的模型没有改变时,为什么会改变它们.
一个简单的例子:
表视图单元格与按钮“喜欢”.当我单击其中一个单元格中的按钮时,按钮文本更改为“不同”(到目前为止这么好).但是当我向下滚动时,即使我没有选择它们,其他单元格也显示“不同”.当我向上滚动时,我最初选择的单元格再次更改,较新的单元格也会更改.
我似乎没有想到这一点.如果你能给我一个工作示例的源代码,那将是真棒!谢谢!
- (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]; }
解决方法@H_301_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,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;
}
-(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];
}
}
根据您当前的逻辑,您正在创建一个新的按钮实例,一直在单元格重新出现.
我建议如下:
- (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,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; }
-(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]; } }