【问题标题】:iOS - Loop through Cells and retrieve dataiOS - 循环遍历单元格并检索数据
【发布时间】:2012-02-13 16:33:37
【问题描述】:

抱歉,我是 iOS 开发新手。

我有一个UITableView 设置来自从单个 XiB 笔尖拉出的单元格。我在笔尖中创建了一个开/关开关,我试图将开关的状态保存在viewWillDisappear 上,以获取我拥有的单元格数量。 (准确地说是 6 个单元格)。

如何遍历所有单元格并保存这些信息?

我在我的 UIViewController 中尝试了这个来获取一个单元格的信息:

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];

    UITableView *tv = (UITableView *)self.view;
    UITableViewCell *tvc = [tv cellForRowAtIndexPath:0];

}

它给了我错误“程序接收信号:“EXC_BAD_INSTRUCTION”。

我怎样才能做到这一点?

【问题讨论】:

  • 为什么要声明tv?你不能用self.tableView吗?
  • 您不应将开关状态存储在单元格中。使用 NSArray 进行数据模型存储
  • 我同意 NeverBe - 不要按照您描述的方式进行操作(可能的例外是您有一张小桌子,并且已将单元格定义为不可重复使用)。使用 tableviews 的推荐方法是在单独的 model 中维护状态。 当用户进行更改时,您可以使用更改更新该模型,方法是将处理程序添加到每个字段的 editDidEnd 或类似方法。然后当“完成”时,您正在检查您的自定义模型数据 - 不需要显示的字段。

标签: ios uitableview viewwillappear


【解决方案1】:

您必须将有效的NSIndexPath 传递给cellForRowAtIndexPath:。您使用了 0,这意味着没有 indexPath。

你应该使用这样的东西:

UITableViewCell *tvc = [tv cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];

但是。不要这样做。 不要在 UITableViewCell 中保存状态。
当开关改变其状态时更新您的数据源。

如果您已经实现了 UITableViewDataSource 方法,那么您的 tableView 重用单元格的正确原因。这意味着当单元格被重复使用时,您的单元格的状态将消失。

您的方法可能适用于 6 个单元格。但它会失败 9 个单元格。
如果您将第一个单元格滚动到屏幕外,它甚至可能会失败。


我写了一个快速演示(如果您不使用 ARC,请在必要的地方添加 release)来向您展示应该如何做:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.dataSource = [NSMutableArray arrayWithCapacity:6];
    for (NSInteger i = 0; i < 6; i++) {
        [self.dataSource addObject:[NSNumber numberWithBool:YES]];
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        UISwitch *aSwitch = [[UISwitch alloc] init];
        [aSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
        cell.accessoryView = aSwitch;
    }
    UISwitch *aSwitch = (UISwitch *)cell.accessoryView;
    aSwitch.on = [[self.dataSource objectAtIndex:indexPath.row] boolValue];
    /* configure cell */
    return cell;
}

- (IBAction)switchChanged:(UISwitch *)sender 
{
//    UITableViewCell *cell = (UITableViewCell *)[sender superview];
//    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    CGPoint senderOriginInTableView = [sender convertPoint:CGPointZero toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:senderOriginInTableView];
    [self.dataSource replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:sender.on]];
}

如您所见,不在单元格中存储状态并不是很复杂 :-)

【讨论】:

  • +1 表示您的回复。您的方法是否也适用于单元格内的文本字段?例如,当我创建一个带有文本字段的单元格时,我可以说[cell.textfield addTarget:self action:@selector(updateField:) forControlEvents:UIControlEventValueChanged];。这允许在每次值更改时更新相应的模型。这会引入开销吗?注册文本字段代表(例如didEndEditing)并在那里更新模型会更容易吗?谢谢。
  • 谢谢马蒂亚斯。我只是在编写将标记状态保存到单元格中的逻辑,并且我已经停止刷新数据源,但是请注意,如果单元格由于滚动而重新加载,我将失去该状态。
【解决方案2】:

[super viewDidDisappear:animated]; 移动到方法的末尾可能是解决问题的最方便的方法。如果这不起作用,请将逻辑移至viewWillDisappear:animated:

解决这个问题的更好方法是完全避免从视图中读取当前状态。相反,视图应该在每次更新时将状态传递给 model。这样,您就可以从模型中获取当前状态,完全独立于 视图 的状态。

【讨论】:

  • 您是说要保存视图而不是单元格内的不同选择吗?
  • @Romes 不,我说的是您的 MVC 实现中的 Model object。它应该具有您系统的最新状态,与您的视图显示完全相同的方式。您应该能够随时获取并保存此模型对象,包括视图完全消失的时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多