问题描述
好的.我似乎无法对 tableviews 的工作方式有一个坚定的理解.有人可以向我解释一下如何在表格视图中重用单元格,尤其是在滚动时?我对此的主要痛点之一是,当我在一个单元格中创建一个动作时,当我滚动时其他单元格会受到影响.我尝试使用数组作为模型的后端,但我仍然得到了不应该改变的单元格.很难弄清楚为什么当数组中的模型没有改变时它们会改变.
Ok. I cant seem to get a firm understanding on how tableviews work. Would someone please explain to me how cells are reused in tableviews especially when scrolling? One of the major pain points I have about this is the fact that when I create an action in one cell, other cells are affected when I scroll. I tried using an array as the backend for the model but still I get cells that change when not suppose to. The hard thing to figure out is why do they change when the the model in the array is not changed.
一个简单的例子:
带有喜欢"按钮的表格视图单元格.当我单击其中一个单元格中的按钮时,按钮文本变为不喜欢"(到目前为止一切都很好).但是当我向下滚动时,即使我没有选择它们,其他单元格也会显示不像".当我向上滚动时,我最初选择的单元格会再次更改,并且更新的单元格也会更改.
table view cells with the button "like". When I click the button in one of the cells, the button text changes to "Unlike"(So far so good). But When I scroll down, other cells also show "Unlike" even though I haven't selected them. And when I scroll up, the cells I originally selected change again and newer ones are changed as well.
我似乎无法弄清楚这一点.如果你能给我看一个工作示例源代码,那就太棒了!!!谢谢!
I cant seem to figure this out. If you can show me a working example source code, that would be awesome!!! Thanks!
- (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];
}
推荐答案
我假设您是通过 Storyboard
执行此操作的,因为您还没有通过 Interface Builder<创建按钮/code>,您需要检查正在重复使用的单元格是否已经有按钮.
根据您当前的逻辑,每次单元格重新出现时,您都会创建一个新的按钮实例.
I am assuming you are doing this via Storyboard
and since you haven't created your button via the Interface Builder
, you need to check if the cell that is being re-used already has the button or not.
As per your current logic, you are creating a new button instance ever time the cell reappears.
我建议如下:
- (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;
}
<小时>
-(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];
}
}
这篇关于如何在 uitableview for IOS 中使用可重用单元的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!