我是Objective-c的初学者。搜索了很多,但没有解决我的问题。我在tableview中有一个单元格原型,它有多个标签和一个按钮。按钮将根据服务器端数据处于非活动状态和活动状态。例如,如果feedback = close
,该按钮将处于非活动状态且仅显示文本关闭,如果feedback = action
,该按钮将显示在单元格原型设计期间在故事板中设置的图像。按钮单击将执行一些操作。我的问题是,我的tableview第一次按预期显示数据,但在滚动按钮图像上显示changed to the text close
。这是我的代码。添加屏幕截图以便清晰我必须对按钮单击和行单击执行两个不同的操作
screenshot
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TransactionCell *cell = [tableView dequeueReusableCellWithIdentifier:@"customTransactionCell" forIndexPath:indexPath];
if (cell==nil)
{
cell = [[TransactionCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"customTransactionCell"];
}
// Configure the cell.
if([[[transactionList objectAtIndex:indexPath.row]valueForKey:@"action"]isEqualToString:@"Close"]){
[cell.feedbackButton setImage:nil forState:UIControlStateNormal];
[cell.feedbackButton setTitle:@"Close" forState:(UIControlStateNormal)];
}
else
if([[[transactionList objectAtIndex:indexPath.row]valueForKey:@"action"]isEqualToString:@"Open"])
{
[cell.feedbackButton setImage:nil forState:UIControlStateNormal];
[cell.feedbackButton setTitle:@"Open" forState:(UIControlStateNormal)];
}
else
{
cell.feedbackButton.tag = indexPath.row;
[cell.feedbackButton addTarget:self action:@selector(feedbackButtonClick:) forControlEvents:UIControlEventTouchUpInside];
}
return cell;
}
答案 0 :(得分:1)
您的单元格正在被重用,这意味着重用后的单元格将保存您在上次使用时设置的所有设置。这意味着在最后一个(action:@selector(feedbackButtonClick:)
)中,单元格不会更改在上次使用单元格期间继承的视觉设置。您必须也不必重置单元格(更好地通过覆盖-[TransactionCell prepareForReuse]
)或为逻辑的每种情况设置视觉效果,而不必跳过以前的设计设置。
那么你的具体情况没有例子,因为我不知道你的默认UI设置,但它会像
- (void)prepareForReuse {
[super prepareForReuse];
[self.feedbackButton setImage:<DEFAULT IMAGE> forState:UIControlStateNormal];
[cell.feedbackButton setTitle:<DEFAULT TITLE> forState:(UIControlStateNormal)];
[cell.feedbackButton removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents];
}
答案 1 :(得分:0)
这是由UITableView设计用于重用单元格的方式引起的。当您的代码使可重用单元格出列时,它仍将处于上次使用该单元格时所配置的状态。
在评估“transactionList”之前,您应该在“cellForRowAtIndexPath”中手动设置图像。
更好 我建议你创建一个单元格重置功能,你可以在“cellForRowAtIndexPath”的开头发信息。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TransactionCell *cell = [tableView dequeueReusableCellWithIdentifier:@"customTransactionCell" forIndexPath:indexPath];
if (cell==nil)
{
cell = [[TransactionCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"customTransactionCell"];
}
// Configure the cell.
[self resetCell:cell];
...
}
-(void)resetCell:(TransactionCell *)cell
{
//reset any variables you may have changed from the reused cell
[cell. feedbackButton setBackgroundImage:buttonImage forState:UIControlStateNormal];
}
答案 2 :(得分:0)
您的实施中存在两个问题。让我逐一描述一下&amp;试着解决它们
第1期
在最后的其他情况下,您使用以下代码段添加target selector
[cell.feedbackButton addTarget:self action:@selector(feedbackButtonClick:) forControlEvents:UIControlEventTouchUpInside];
UITableView旨在重复使用相同的单元格来显示另一组数据,因此每次执行此else
时,都会多次添加相同的操作。您可以在TransactionCell
或awakeFromNib
之类的任何其他init
方法中仅在initWithStyle:reuseIdentifier:
的实施中声明目标。这就是一个按钮在按下一次时只会产生一次反应的方式。
您的TransactionCell.m
应如下所示
- (instancetype)initWithStyle:(UITableViewCellStyle)style
reuseIdentifier:(NSString *)id
{
self = [super initWithStyle:style reuseIdentifier:id];
if(self)
{
[self.feedbackButton addTarget:self action:@selector(feedbackButtonClick:) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
-(IBAction)feedbackButtonClick:(id)sender
{
//do your feedback action according to your data
}
如果您正在使用nib / storyboard,则无需手动addTarget
中的initWithStyle: reusingIdentifier:
,只需使用助手将nib / storyboard中的IBAction
添加到目标操作中查看xcode&amp;无视窗格。
第2期
您正在设置所需状态按钮的状态,而不关心其他状态。这是负责的代码部分
if([[[transactionList objectAtIndex:indexPath.row]valueForKey:@"action"]isEqualToString:@"Close"]){
[cell.feedbackButton setImage:nil forState:UIControlStateNormal];
[cell.feedbackButton setTitle:@"Close" forState:(UIControlStateNormal)];
}
else
if([[[transactionList objectAtIndex:indexPath.row]valueForKey:@"action"]isEqualToString:@"Open"])
{
[cell.feedbackButton setImage:nil forState:UIControlStateNormal];
[cell.feedbackButton setTitle:@"Open" forState:(UIControlStateNormal)];
}
您应该指定按钮的状态,如下所示
if(/* open case */)
{
cell.feedbackButton.enabled = NO;
//other configuration like title / image
}
else if(/*close case*/)
{
cell.feedbackButton.enabled = NO;
//other configuration like title / image
}
else if(/* feedback case */)
{
cell.feedbackButton.enabled = YES;
//other configuration like title / image
}
永远不要试图通过为每个数据创建新单元来停止重复使用相同的单元格。除了重复使用相同的UITableViewCell
之外,它将导致更大的内存跟踪。
快乐的编码。