确定。我似乎无法深入了解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];
}
答案 0 :(得分: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;
}
-(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];
}
}
答案 1 :(得分:3)
最大的问题是每次更新单元格时都会创建按钮。
例如,如果您在屏幕上有可见的4个roes,请执行以下操作:
*-----------------------*
| cell A with button |
*-----------------------*
| cell B with button |
*-----------------------*
| cell C with button |
*-----------------------*
| cell D with button |
*-----------------------*
现在当你向下滚动以便单元格A不再可见时,它会被重用并放在下面:
*-----------------------*
| cell B with button |
*-----------------------*
| cell C with button |
*-----------------------*
| cell D with button |
*-----------------------*
| cell A with button |
*-----------------------*
但是对于单元格A,它再次被称为cellForRowAtIndexPath
。
你做的是在它上面放置另一个按钮。所以你实际上有:
*-----------------------*
| cell B with button |
*-----------------------*
| cell C with button |
*-----------------------*
| cell D with button |
*-----------------------*
| cell A with 2 buttons |
*-----------------------*
你可以看到你很快就会有很多按钮堆积起来。您可以通过@Timur Kuchkarov建议的故事板来修复此问题,或者通过
修复代码- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
if (cell ==nil) {
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 = 10;
[cell.contentView addSubview:myButton];
}
UIButton * myButton = (UIButton * )[cell.contentView viewWithTag:10]
if ([[likeState objectAtIndex:indexPath.row]boolValue]==NO) {
[myButton setTitle:@"Like" forState:UIControlStateNormal];
}
else{
[myButton setTitle:@"Unlike" forState:UIControlStateNormal];
}
return cell;
}
这样你只需添加一个按钮,如果没有重复使用单元格(因此它没有任何内容)。
通过这种方式,您不能依赖羊肉标签号码来点击功能,(我不管怎么说),所以你必须改变它。
此部分未经过测试:
您可以检查按钮的父级以查看它所属的女性单元格。
UITableViewCell * cell = [[button superview] superview] /// superview of button is cell.contentView
NSIndexPath * indexPath = [yourTable indexPathForCell:cell];
答案 2 :(得分:2)
要重新使用单元格,请将您的单元格标识符值放在界面构建器中。
答案 3 :(得分:1)
首先,当你点击单元格按钮时,你总是设置@(1)([NSNumber numberWithInt:1],最好使用@(YES)或@(NO))。这就是为什么你会看到不正确的结果。然后你总是在你的单元格中添加按钮,所以如果它被重复使用了10次,你就可以在那里添加10个按钮。最好使用xib或storyboard原型。
答案 4 :(得分:1)
接受答案的Swift 2.1版本。对我很有用。
override func viewDidLoad() {
super.viewDidLoad();
self.arrayProducts = NSMutableArray(array: ["this", "that", "How", "What", "Where", "Whatnot"]); //array from api for example
var i:Int = 0;
for (i = 0; i<=self.arrayProducts.count; i++){
let numb:NSNumber = NSNumber(bool: false);
self.arrayFavState.addObject(numb); //array of bool values
}
}
TablView数据源方法::
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("SubCategoryCellId", forIndexPath: indexPath) as! SubCategoryCell;
cell.btnFavourite.addTarget(self, action: "btnFavouriteAction:", forControlEvents: UIControlEvents.TouchUpInside);
var isFavourite: Bool!;
isFavourite = self.arrayFavState[indexPath.row].boolValue;
if isFavourite == true {
cell.btnFavourite.setBackgroundImage(UIImage(named: "like-fill"), forState: UIControlState.Normal);
} else {
cell.btnFavourite.setBackgroundImage(UIImage(named: "like"), forState: UIControlState.Normal);
}
return cell;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrayProducts.count;
}
按钮操作方法::
func btnFavouriteAction(sender: UIButton!){
let position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableProducts)
let indexPath = self.tableProducts.indexPathForRowAtPoint(position)
let cell: SubCategoryCell = self.tableProducts.cellForRowAtIndexPath(indexPath!) as! SubCategoryCell
//print(indexPath?.row)
//print("Favorite button tapped")
if !sender.selected {
cell.btnFavourite.setBackgroundImage(UIImage(named: "like-fill"), forState: UIControlState.Normal);
sender.selected = true;
self.arrayFavState.replaceObjectAtIndex((indexPath?.row)!, withObject:1);
} else {
cell.btnFavourite.setBackgroundImage(UIImage(named: "like"), forState: UIControlState.Normal);
sender.selected = false;
self.arrayFavState.replaceObjectAtIndex((indexPath?.row)!, withObject:0);
}
}
答案 5 :(得分:0)
我需要查看您的代码,但我可以说您没有更改模型或者您更改了数组中的所有行。
您可以使用从UITableViewCell扩展的某些类,并在“cellForRowAtIndexPath”方法中将其用作可重复使用的单元格。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell"];
// Configure the cell...
MyModel *model = [_models objectAtIndex:indexPath.row];
cell.nameLabel.text = model.name;
cell.image.image = model.image;
cell.likeButton.text = model.likeButtonText;
return cell;
}
然后在“didSelectRowAtIndexPath”方法中更改“model.likeButtonText”。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
MyCell cell* = [tableView cellForRowAtIndexPath:indexPath];
MyModel *model = [_models objectAtIndex:indexPath.row];
model.likeButtonText = [model.likeButtonText isEqual:@"like"]?@"unlike":@like;
cell.likeButton.text = model.likeButtonText;
}
这将更新你的手机