【问题标题】:iOS Dynamic Form in UITableViewCells, Retrieve ValuesUITableViewCells中的iOS动态表单,检索值
【发布时间】:2015-02-03 14:21:24
【问题描述】:

我一直在搜索和阅读,但找不到任何确凿的方法来实现我想要的,并希望在这里找到帮助......

我有一个 UITableView,它允许用户向食谱添加多种口味和百分比。我已经实现了使用自定义 Cell / Nib 添加或删除 Flavour 行的方法,并且效果很好。

我现在面临的问题是如何检索用户为每个添加的行提供的值

(为清晰而编辑:我的问题不是填充数据,而只是动态读取所有数据,以便我可以保存它)

我确实设法获取了可见行的值(我确实了解 Reuseidentifier 和 Tableview 的工作原理,就内存管理而言,iOS 仅跟踪可见行),而不是隐藏行。

理论上我假设我必须在 'cellForRowAtIndexPath' 之外创建一个单元格数组,以维护所有单元格。但后来我面临另一个概念问题,我的自定义笔尖/单元格没有显示......基本上:

  • 如何在不使用 dequeingidentifier 的情况下使用/注册 nib
  • 或者一般来说,我如何解决总体问题,以便能够读取每行所有用户输入的值

这是我在 cellForRowAtIndexPath 中使用的代码。如前所述,添加和删除单元格就像一个魅力,这不是问题......

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

RecipeFlavourTableViewCell *cell;
int section = (int)indexPath.section;

if(section==0)
    return [super tableView:tableView cellForRowAtIndexPath:indexPath];


if(!cell){
    [tableView registerNib:[UINib nibWithNibName:@"RecipeFlavourCell" bundle:nil] forCellReuseIdentifier:@"Cell"];
    cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
}

cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;

}

我见过一些图书馆这样做(例如 XLForm),但不明白(在检查它们的来源时)他们如何遍历值并克服这个出队问题......

非常感谢任何帮助

编辑 2:这里是我用来遍历单元格以保存数据的代码,但如前所述,我只能遍历可见单元格:

- (IBAction)saveRecipe:(id)sender {

NSInteger dynamicRows = [self.tableView numberOfRowsInSection:1];

    for (int i=0; i<dynamicRows; i++) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:1];
        RecipeFlavourTableViewCell *cell = (RecipeFlavourTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
        NSLog(cell.flavour.text);
    }

}

【问题讨论】:

  • 将填充到表格中的信息保存在哪里?
  • 如下所述,我的问题不是填充,而是读取和保存用户输入的数据
  • 当你没有很好地将模型与视图分离时,这是你遇到的典型问题......我认为一个人可以过度使用整个 MVC 架构,但这是一个非常好东西。你真的想要一个用于填充单元格的底层数据模型(最初是空的,是的),以及一个单独的控制器来维护用户输入的当前数据,并在 UI 中挂钩以在新模型时不断更新模型值已输入。
  • @RobP 我终于得出了类似的结论,请看下面我的回答
  • 我建议的不同之处在于,您不保留 UITableViewCells 数组。你有一个组件,它的工作是以你自己有用的抽象形式保存一堆配方数据——最初可能是一个 NSArray。您从该数据填充 UITableViewCells,然后编辑单元格返回以更改该数据。那么底层的数据表示就可以直接搬到CoreData而不是NSArray中了,所有UI相关的代码都不用改了。

标签: ios iphone forms uitableview dynamic


【解决方案1】:

经过 2 天的搜索,我终于想出了一个可靠的解决方案。如果有人在使用 tableview 时遇到同样的动态表单问题,这里的解决方案是:

据我们了解,在 cellForRowAtIndexPath 中创建的任何单元格都只会在显示时持续存在。一旦您滚动并且单元格消失,它就会自动从内存中抛出。这种行为使得在以后的阶段无法遍历所有单元格。

为了使它工作,要遵循的步骤如下:

准备

  • 创建一个 NSObject,其中包含您希望在一个表单单元格 (-> cellObject) 中保留的所有属性
  • 在控制器的 ViewDidLoad 中创建一个 NSMutableArray,其中将包含 cellObjects (-cellsArray)
  • 将尽可能多的 cellObject 添加到 cellsArray,就像您最初希望出现在 Tableview 中一样
  • 在 numberOfRowsInSection 中返回你的 cellsArray 数量
  • 在 cellForRowAtIndexPath 中像往常一样构建您的单元格,但向单元格中的每个 Textfield 添加一个 Textfield Delegate (self)

TextField 委托

实施:

 - (void)textFieldDidEndEditing:(UITextField *)textField

并在每次文本字段结束编辑时更新您的 cellsArray 对象。本质上,获取该行的 cellObject 并使用 TextField 的值编辑属性

添加行

当您添加一行时,只需将一个空的 cellObject 添加到您的 cellsArray 并在您的 tableView 上使用 beginUpdates / insertRowsAtIndexPaths / endUpdates (不要 reloadData,因为已经输入的数据会丢失)。还要在 addRow 方法的最开始添加以下内容,因为您要确保如果用户在编辑文本字段时添加一行,后者也会被持久化:

 [self.view.window endEditing: YES];

删除行

与 Add Row 相同,只是反转,从 cellsArray 中删除 cellObject 并在 tableView 上使用 deleteRowsAtIndexPaths

保存数据

现在的诀窍是:由于您应该始终在字段结束编辑模式时保留您的数据,因此您需要涵盖一种情况:如果用户在焦点设置在一个 TextField 上时按下“保存”会怎样?那么在您保存操作的最开始插入以下内容:

 [self.view.window endEditing: YES];

这确保了当前 textField 的 textFieldEndEditing 将被最后一次触发,并且它的数据也将被持久化。

最后遍历你的 cellsArray 并用它做任何你想做的事情(验证、保存等)...

就是这样,希望这可以帮助其他人,因为我在其他任何地方都找不到任何有价值的解释......

【讨论】:

  • 最好的做法是为 TableView 中的每个 UITextField 属性分配一个唯一的整数到 tag。这样您就可以轻松区分哪个textField 已结束编辑。
【解决方案2】:

假设您有一个 NSArray 并且它包含您要显示的数据。您的代码应如下所示:

// Add this property to the class and fill it in with data you want to show
@property NSArray flavourElements;

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    RecipeFlavourTableViewCell *cell;
    int section = (int)indexPath.section;

    if(section==0)
        return [super tableView:tableView cellForRowAtIndexPath:indexPath];


    if(!cell){
        [tableView registerNib:[UINib nibWithNibName:@"RecipeFlavourCell" bundle:nil] forCellReuseIdentifier:@"Cell"];
        cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
        // At this point your cell is ready for showing
        // And you can change values in it by getting element from array that contains data
        cell.flavorTextField = flavourElements[indexPath.row].flavour
        cell.precentageTextField = flavourElements[indexPath.row].precentage        
    }

    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    return cell;

}

我编写了一个代码来访问元素而不知道你实际拥有什么,所以你需要稍微调整它以适应你的应用程序。

【讨论】:

  • 您的示例描述了如何将数据填充到 tableview 中,但这不是我的问题。我的问题是,当用户打开视图时,还没有数据(基本上他创建了一个新对象),他需要提供数据。所以我需要的是能够遍历所有的行/数据,这样我就可以将它保存到 Core Data
  • 好的,所以你很少错过代码。上面的答案向您展示了如何在表中获取数据,但假设您在数组中获取它。给我更多关于 Core Data 的内容,这样我就可以给你写一些代码。
  • 感谢@TheLittleHawk 的提议,关键是还没有核心数据,它必须以那种形式创建。简而言之,用户以这种形式创建一个新的核心数据条目,然后按下保存。所以我的问题是遍历这些动态行(注意他可以在标题中使用加号按钮添加一行)并将它们保存到核心数据中
  • 我添加了另一段代码来显示我当前如何尝试保存数据,但如上所述,我只能遍历可见单元格而不是隐藏单元格
  • 阿哈姆,好的。您是否尝试过 Xcode 的模板 Master-Detail 项目?如果您在开始时选择 Core Data 复选框,它将为您提供创建数据库 (SQLite) 并将项目保存到其中所需的所有代码。此外,它还为每一行保存了 + 和删除按钮。您可以将该代码复制/粘贴到您的项目中以开始使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-27
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
  • 2015-04-07
相关资源
最近更新 更多