UITableViewCell 中的最终 UIButton 是不可变的
Posted
技术标签:
【中文标题】UITableViewCell 中的最终 UIButton 是不可变的【英文标题】:Final UIButton in a UITableViewCell is unmutable 【发布时间】:2017-01-12 23:18:11 【问题描述】:我有一个 UITableView(和关联的单元格),其中包含可变数量的项目。每个单元格内都有与正在显示的对象相关联的值。还有一个按钮允许用户说明正在显示的任务(来自对象属性)是否完成。它应该改变颜色并变得活跃。这有效,除了列表中的最后一项。这是不工作的代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TasksItem"];
[BAPAppDelegate setBorder:[cell viewWithTag:300] withBorder:[BAPAppDelegate darkGreyColor]];
[BAPAppDelegate setBorder:[cell viewWithTag:301] withBorder:[UIColor blackColor]];
[BAPAppDelegate setBorder:[cell viewWithTag:1000] withBorder:[UIColor blackColor]];
ServiceRequest *sr = (mListTasks)[indexPath.row];
[(UILabel *)[cell viewWithTag:110] setText:sr.vSRType];
UILabel *smry = (UILabel *)[cell viewWithTag:301];
smry.text = [NSString stringWithFormat:@"%@", [sr vMTSmry]]; // check if completed
int cnt;
int complete;
UIButton* btn;
cnt = [sr getBeforeRequired];
complete = [sr getBeforeCompleted];
markCompleteButton = YES;
btn = (UIButton *)[cell viewWithTag:120];
if (cnt > 0)
[btn setHidden:NO];
[btn setTitle:[NSString stringWithFormat:@"%i", cnt] forState:UIControlStateNormal];
else
[btn setTitle:@"0" forState:UIControlStateNormal];
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
if (complete < cnt)
[btn setTitleColor:[BAPAppDelegate redColor] forState:UIControlStateNormal];
[self markComplete:NO];
else
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
cnt = [sr getDuringRequired];
complete = [sr getDuringCompleted];
btn = (UIButton *)[cell viewWithTag:121];
if (cnt > 0)
[btn setHidden:NO];
[btn setTitle:[NSString stringWithFormat:@"%i", cnt] forState:UIControlStateNormal];
else
[btn setTitle:@"0" forState:UIControlStateNormal];
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
if (complete < cnt)
[btn setTitleColor:[BAPAppDelegate redColor] forState:UIControlStateNormal];
[self markComplete:NO];
else
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
cnt = [sr getAfterRequired];
complete = [sr getAfterCompleted];
btn = (UIButton *)[cell viewWithTag:122];
if (cnt > 0)
[btn setHidden:NO];
[btn setTitle:[NSString stringWithFormat:@"%i", cnt] forState:UIControlStateNormal];
else
[btn setTitle:@"0" forState:UIControlStateNormal];
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
if (complete < cnt)
[btn setTitleColor:[BAPAppDelegate redColor] forState:UIControlStateNormal];
[self markComplete:NO];
else
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
cnt = [sr getCheckRequired];
complete = [sr getCheckCompleted];
btn = (UIButton *)[cell viewWithTag:123];
if (complete < cnt)
[btn setTitleColor:[BAPAppDelegate redColor] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:@"check_red.png"] forState:UIControlStateNormal];
[self markComplete:NO];
else
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:@"check.png"] forState:UIControlStateNormal];
btn = (UIButton *)[cell viewWithTag:1000];
[btn setTag:indexPath.row + 1001];
if (markCompleteButton)
[btn setBackgroundColor:[BAPAppDelegate greenColor]];
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[btn setEnabled:YES];
[btn setTitle:@"YEP" forState:UIControlStateNormal];
NSLog(@"YEP %ld", (long)indexPath.row);
else
[btn setEnabled:NO];
NSLog(@"NOPE %ld", (long)indexPath.row);
[cell prepareForReuse];
return cell;
正如预期的那样,日志显示“YEP 8”,但按钮本身没有任何变化。列表中前面的其他按钮按预期显示并执行其操作。
任何见解将不胜感激!
【问题讨论】:
需要更多上下文(更多代码)来帮助,但作为一个疯狂的猜测,它是屏幕外的第 8 个单元格?如果是这样,我怀疑它正在被重用,并且它的状态与您期望的不一样。看看 UITableViewCell prepareForReuse 方法。 没有更多的代码可以添加,坦率地说,这是一个非常枯燥的实现,这就是我如此困惑的原因。但是,它确实在首屏下方,因此确实需要滚动到其他正常工作的位置。我将编辑我的代码片段以提供一些额外的上下文。 【参考方案1】:我最终将 UITableViewCell 子类化并将 UITableViewCell 从我的故事板连接到我的子类,然后将按钮的插座连接到子类。此外,我将按钮的操作设置为转到子类。
TasksCell.h
@protocol TasksCellDelegate <NSObject>
- (void)buttonPressed:(UIButton *)sender;
@end
@interface TasksCell : UITableViewCell
@property (weak, nonatomic) id<TasksCellDelegate> delegate;
@property (weak, nonatomic) IBOutlet UIButton *button;
- (IBAction)buttonPressed:(UIButton *)sender;
@end
TasksCell.m:
#import "TasksCell.h"
@implementation TasksCell
- (id)initWithFrame:(CGRect)frame
self = [super initWithFrame:frame];
if (self)
// Initialization code
return self;
- (IBAction)buttonPressed:(UIButton *)sender
[self.delegate buttonPressed:sender];
@end
TasksViewController.h
#import "TasksCell.h"
TasksViewController.m:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
TasksCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:@"TasksItem"
forIndexPath:indexPath];
[BAPAppDelegate setBorder:[cell viewWithTag:300] withBorder:[BAPAppDelegate darkGreyColor]];
[BAPAppDelegate setBorder:[cell viewWithTag:301] withBorder:[UIColor blackColor]];
[BAPAppDelegate setBorder:[cell viewWithTag:1000] withBorder:[UIColor blackColor]];
ServiceRequest *sr = (mListTasks)[indexPath.row];
[(UILabel *)[cell viewWithTag:110] setText:sr.vSRType];
UILabel *smry = (UILabel *)[cell viewWithTag:301];
smry.text = [NSString stringWithFormat:@"%@", [sr vMTSmry]]; // check if completed
int cnt;
int complete;
UIButton* btn;
cnt = [sr getBeforeRequired];
complete = [sr getBeforeCompleted];
markCompleteButton = YES;
btn = (UIButton *)[cell viewWithTag:120];
if (cnt > 0)
[btn setHidden:NO];
[btn setTitle:[NSString stringWithFormat:@"%i", cnt] forState:UIControlStateNormal];
else
[btn setTitle:@"0" forState:UIControlStateNormal];
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
if (complete < cnt)
[btn setTitleColor:[BAPAppDelegate redColor] forState:UIControlStateNormal];
[self markComplete:NO];
else
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
cnt = [sr getDuringRequired];
complete = [sr getDuringCompleted];
btn = (UIButton *)[cell viewWithTag:121];
if (cnt > 0)
[btn setHidden:NO];
[btn setTitle:[NSString stringWithFormat:@"%i", cnt] forState:UIControlStateNormal];
else
[btn setTitle:@"0" forState:UIControlStateNormal];
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
if (complete < cnt)
[btn setTitleColor:[BAPAppDelegate redColor] forState:UIControlStateNormal];
[self markComplete:NO];
else
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
cnt = [sr getAfterRequired];
complete = [sr getAfterCompleted];
btn = (UIButton *)[cell viewWithTag:122];
if (cnt > 0)
[btn setHidden:NO];
[btn setTitle:[NSString stringWithFormat:@"%i", cnt] forState:UIControlStateNormal];
else
[btn setTitle:@"0" forState:UIControlStateNormal];
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
if (complete < cnt)
[btn setTitleColor:[BAPAppDelegate redColor] forState:UIControlStateNormal];
[self markComplete:NO];
else
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
cnt = [sr getCheckRequired];
complete = [sr getCheckCompleted];
btn = (UIButton *)[cell viewWithTag:123];
if (complete < cnt)
[btn setTitleColor:[BAPAppDelegate redColor] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:@"aprsi_check_red.png"] forState:UIControlStateNormal];
[self markComplete:NO];
else
[btn setTitleColor:[BAPAppDelegate greenColor] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:@"aprsi_check.png"] forState:UIControlStateNormal];
[cell.button setTag:indexPath.row + 1001];
if (markCompleteButton)
cell.button.backgroundColor = [BAPAppDelegate greenColor];
[cell.button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[cell.button setEnabled:YES];
NSLog(@"YEP %ld", (long)indexPath.row);
else
[cell.button setTitleColor:[BAPAppDelegate darkGreyColor] forState:UIControlStateDisabled];
[cell.button setBackgroundColor:[BAPAppDelegate lightGreyColor]];
[cell.button setEnabled:NO];
NSLog(@"NOPE %ld", (long)indexPath.row);
[cell prepareForReuse];
return cell;
为了让按钮按预期工作,我将按钮委托保留在 TasksViewController 中,但同样可以轻松地将其移至子类。希望这可以帮助某人!
【讨论】:
以上是关于UITableViewCell 中的最终 UIButton 是不可变的的主要内容,如果未能解决你的问题,请参考以下文章
动态添加和删除 UITableViewCells 到 UITableView
在 UITableViewCell 中检测具有灵活宽度的视图的最终布局大小
UITableViewCell 子类,在代码中绘制,动画中的删除按钮
在 UITableViewCell 中调整 UITextView 的大小