保存 UITableView 单元格附件的状态?
Posted
技术标签:
【中文标题】保存 UITableView 单元格附件的状态?【英文标题】:Saving state of UITableView cell accessory? 【发布时间】:2012-12-28 18:09:53 【问题描述】:我在表格视图中设置了手势识别器。
向右滑动,配件会变为刻度图像 向左滑动,变为 V 形图像如果一个单元格被点击,它会加载一个本地 html 文件。
如果您向右滑动,勾号会按原样显示。但是,如果您随后点击单元格以查看 HTML 文件并返回表格视图,则图像将恢复为 V 形。
确保滴答声保持应有状态的最佳方法是什么?
编辑
更多代码:
来自“viewDidLoad”:
UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self
action:@selector(handleSwipeRight:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[self.tableView addGestureRecognizer:recognizer];
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self
action:@selector(handleSwipeLeft:)];
//recognizer.delegate = self;
[recognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)];
[self.tableView addGestureRecognizer:recognizer];
- (void)handleSwipeLeft:(UISwipeGestureRecognizer *)gestureRecognizer
//Get location of the swipe
CGPoint location = [gestureRecognizer locationInView:self.tableView];
//Get the corresponding index path within the table view
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
//Check if index path is valid
if(indexPath)
//Get the cell out of the table view
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
//Update the cell or model
cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"disclosure.png"]];
- (void)handleSwipeRight:(UISwipeGestureRecognizer *)gestureRecognizer
CGPoint location = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
if(indexPath)
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
// cell.accessoryType = UITableViewCellAccessoryCheckmark;
cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"tick.png"]];
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *simpleTableIdentifier = @"MFGCell";
MFGCell *cell = (MFGCell *) [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"MFGCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.itemTitle.text = [item objectAtIndex:indexPath.row];
cell.itemDescription.text = [description objectAtIndex:indexPath.row];
cell.itemImageView.image = [UIImage imageNamed:[icons objectAtIndex:indexPath.row]];
return cell;
【问题讨论】:
保留一个数组,其中的值与您对单元格中保存的数据完全相同。 视图可能正在后台卸载以释放内存,当它们重新出现时,它们将依赖 cellForRowAtIndexPath 告诉它们应该如何出现。使该方法适当地显示当前选定的单元格。 【参考方案1】:作为对用户滑动的反应,您应该存储用户的选择(例如,在 NSMutableArray
类型的私有实例变量中)。当用户返回表格视图时,您可以重复使用 tableView:cellForRowAtIndexPath:
中的信息来设置具有正确附件样式的单元格。
财产声明:
@property(nonatomic, retain) NSMutableArray* _accessoryStyle;
综合属性。然后在handleSwipeLeft:
的底部加上这个sn-p来存储用户的选择:
- (void)handleSwipeLeft:(UISwipeGestureRecognizer *)gestureRecognizer
[...]
NSNumber* number = [numberWithInt:0];
[_accessoryStyle replaceObjectAtIndex:indexPath.row withObject:number];
在handleSwipeRight:
的底部添加一个类似的sn-p:
- (void)handleSwipeRight:(UISwipeGestureRecognizer *)gestureRecognizer
[...]
NSNumber* number = [numberWithInt:1];
[_accessoryStyle replaceObjectAtIndex:indexPath.row withObject:number];
在tableView:cellForRowAtIndexPath:
:
NSString* accessoryImageName;
NSNumber* number = [_accessoryStyle objectAtIndex:indexPath.row];
switch ([number intValue])
case 0:
accessoryImageName = @"disclosure.png";
break;
case 1:
accessoryImageName = @"tick.png";
break;
default:
// replace with your error handling code
return nil;
cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:accessoryImageName]];
要使所有这些工作,您需要使用与您希望表格视图具有单元格的相同数量的元素来初始化_accessoryStyle
数组。例如,在您的视图控制器的 viewDidLoad
:
- (void) viewDidLoad
[super viewDidLoad];
self._accessoryStyle = [NSMutableArray arrayWithCapacity:0];
NSNumber* defaultAccessoryStyle = [numberWithInt:0];
int numberOfRows = 17; // get the real number from somewhere
for (int index = 0; index < numberOfCells; ++index)
[_accessoryStyle addObject:defaultAccessoryStyle];
为了平衡这一点,您需要添加
- (void) viewDidUnload
[super viewDidUnload];
self._accessoryStyle = nil;
还有很大的改进空间:
找到更好的变量名 对不同的样式使用枚举,而不仅仅是硬编码数字 0 和 1 不要为每个表格视图单元格分配新的UIImageView
,只需分配其中两个并根据附件样式使用正确的一个
【讨论】:
那么这个应该加到cellForRowAtIndexPath方法中吗?如果有帮助,我在上面添加了一些代码。谢谢。 @mattFllr 是的,将其添加到tableView:cellForRowAtIndexPath:
。看看我编辑的答案,使用你的代码我已经用现在应该更清晰的代码示例对其进行了扩展。
完美,谢谢!现在更有意义了,我已经调整了一些,效果很好!
将其保存到 NSUserDefaults 的最佳方法是什么? Question here
@mattFllr 我已经回答了你的问题。【参考方案2】:
对于您的问题,存在潜在的逻辑问题,因为在不应该触发的情况下触发了向左滑动事件,或者视图只是被卸载并重置为默认值。看看你是否可以在事件触发时记录;否则应保留视图的状态。另外我要做的是添加一个额外的状态变量,例如int currentCellState
,当您输入不同的状态以跟踪您的状态时您会更改它。然后在您的viewDIdLoad
中确保您的所有数据和您的视图是同步的,即currentCellState
的值与您的视图状态相匹配。
【讨论】:
【参考方案3】:执行此操作的最佳方法是将您拥有的图像/按钮放在一个数组中,每次加载视图时都会显示选择了哪个索引的项目。 为此,应将 swipeMethode 修改为类似的内容
-(void)swipeMethod: (UISwipeGestureRecognizer *) sender
if(sender.direction ==
UISwipeGestureRecognizerDirectionLeft && index < [myArray count])
[self setSelectedIndex:index+1 animated:YES];
index++;
else if (sender.direction == UISwipeGestureRecognizerDirectionRight && index > 0)
[self setSelectedIndex:index-1 animated:YES];
index--;
else
return;
在 viewDidLoad 中添加这段代码:
leftRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeMethod:)];
[leftRecognizer setDirection: UISwipeGestureRecognizerDirectionLeft];
[self.tableView addGestureRecognizer:leftRecognizer];
rightRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeMethod:)];
[rightRecognizer setDirection: UISwipeGestureRecognizerDirectionRight];
[self.tableView addGestureRecognizer:rightRecognizer];
【讨论】:
为了使其工作,是否需要将此代码放入 handleSwipeLeft 和 handleSwipeRight 方法中?或者我有没有得到棍子的末端? 这个方法应该替换handleSwipeLeft和handleSwipeRight方法。 我运气不好,我已经在上面添加了我的代码,请您将您的代码重写到我的上下文中好吗?谢谢。以上是关于保存 UITableView 单元格附件的状态?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 3 中保存 UITableViewCell 附件复选标记的状态