有没有办法自动将UITextField绑定到我的数据模型中的变量?

时间:2013-08-06 15:18:05

标签: ios objective-c model-view-controller uitextfield

我正在构建一个视图控制器,我以编程方式将一堆UITextField添加到我的视图中。我想用一些我从CoreData加载的文本预先填充文本字段,但允许用户进入并根据需要更改该文本。然后我需要返回并将该新文本再次保存回CoreData,并使用新值执行计算。保存和加载本身不是问题,但我正在寻找一种跟踪用户更改内容的好方法。

过去,我使用.tagUITextField委托方法的textFieldDidEndEditing:属性完成了此操作。问题是我将在这个视图中有几十个文本域 - 足以让我真的不记得.tag属于我的模型中的变量。我必须回过头来查看我在创建它时分配的标签,这将是一种痛苦,而整个事情确实很容易出错。另外,我将在多个不同的循环中创建文本字段,因此在创建它时为每个文本字段获取唯一标记将很困难(可能不可能?)。

我正在寻找的是一种在我创建它时将UITextField“绑定”到模型中的变量的方法,并且从那时起就知道,每当用户更新该文本字段时,我在模型中指定的值将立即更新以用于将来的计算,并在用户离开屏幕时保存回CoreData。有没有办法做到这一点?

编辑1:另一件需要注意的事情是我的模型本身有点复杂。我有几个不同的自定义NSObject子类,它们都包含我的数据的不同部分。某些对象具有本身是其他自定义对象的属性。我也有字典,其中值将是某些自定义对象的实例。

作为一个例子,我可能有这些对象:

  • MySmallObject1,其中包含属性namesizevalue(所有NSStrings
  • MySmallObject2,其中包含属性datecostNSDateNSNumber
  • MyBigObject,其中包含属性box1box2(分别为MySmallObject1MySmallObject2个实例)
  • theDict,这是一个NSDictionary个实例,其MyBigObject为值

因此,当我构建我的文本字段时,我可能真的会走下一棵看起来像这样的树:

for (NSString *key in [theDict allKeys])
{
    UITextField *txt = [[UITextField alloc] initWithFrame:...];
    txt.text = [[(MyBigObject *)[theDict objectForKey:key] box1] name];
    [self.view addSubview:txt];
}

在这种情况下,我需要知道用户何时更改任何txt中的文本,并通过树更新相应的值。

编辑2:在评论中尝试实施@Till的建议时,我开始阅读tutorial on pointers in C。看起来这是我需要的方式,但是我很难从C世界中获得&*,以便与我在上一次编辑中提到的NSObject子类很好地配合。 Objective-C世界。为了让@Till的建议起作用,我想我需要以某种方式将我的值的内存位置存储在复杂的对象树中。所以我上次编辑的代码块将成为:

.h
@property (nonatomic, strong) NSMutableDictionary *tagDict;

.m
for (NSString *key in [theDict allKeys])
{
    UITextField *txt = [[UITextField alloc] initWithFrame:...];
    txt.text = [[(MyBigObject *)[theDict objectForKey:key] box1] name];
    txt.tag = globalCounter;
    [tagDict addObject:[[(MyBigObject *)[theDict objectForKey:key] box1] name] forKey:[NSString stringWithFormat:@"%d",globalCounter]];
    globalCounter ++;
    [self.view addSubview:txt];
}

globalCounterint的地方,每当我将某些内容放入tagDict时,我就会递增NSArray,这样我就可以保持其唯一性。我想在这种情况下,我可以简单地使用tagDict,它也可以正常工作,并且可能看起来更清洁一点。我的计划是在testFieldDidEndEditing中使用- (void) textFieldDidEndEditing:(UITextField *)textField { *[tagDict objectForKey:[NSString stringWithFormat:@"%d",textField.tag]] = textField.txt; } ,如:

Assigning to 'id' from incompatible type 'NSString *'

这会引发Address expression must be an lvalue or a function designator的错误。我不太确定这意味着什么。有没有办法可以使用“解除引用运算符”来更改我在字典中指向的项目的值?

抛出错误{{1}}。关于这个指针的东西在Objective C世界中是如何工作的,我仍然有点模糊,我认为有些东西我还没有完全理解。

3 个答案:

答案 0 :(得分:0)

你可以使用UITextField+blocks它可能不那么纠缠。如果对象具有类似的接口或使用setText:等方法实现一个协议,则会容易得多。{/ 1}。

答案 1 :(得分:0)

您可以将原始方法与.tag一起使用,但请使用typedef。

typedef enum TFTypes {
    TFModalType1,
    TFModalType2,
    TFModalType3,
    TFModalType4,
    TFModalType5,
    ...
} TFType;

答案 2 :(得分:0)

我最终做的主要是我认为@Till试图提出的建议。我将NSMutableArray *tieArrayint tieCounter添加为@properties到我的视图控制器。我的OP中第一个代码块构建UITextFields的代码现在是:

for (NSString *key in [theDict allKeys])
{
    UITextField *txt = [[UITextField alloc] initWithFrame:...];
    txt.text = [[(MyBigObject *)[theDict objectForKey:key] box1] name];
    [self.view addSubview:txt];

    txt.tag = self.tieCounter;
    self.tieCounter ++;
    [self.tieArray addObject:[[(MyBigObject *)[theDict objectForKey:key] box1] name]];
}

然后在我的textFieldDidEndEditing

- (void) textFieldDidEndEditing:(UITextField *)textField
{
    if ([tieArray objectAtIndex:textField.tag] isKindOfClass:[NSMutableString class]])
    {
        [(NSMutableString *)[tieArray objectAtIndex:textField.tag] setString:textField.text];
    }
    else if (//...More conditions to set other variable types with the syntax as needed)
}

请注意,为了实现这一点,MySmallObject1MySmallObject2的所有属性都需要isKindOfClass:检查所涵盖,实际语法会有所不同,具体取决于哪个类该财产是。

我还没有能够测试这个(并且我的应用程序可能在相当长的一段时间内不会处于可测试状态),但这对我来说是有道理的,并且它不会抛出任何错误或警告。如果我在实际运行时遇到问题,我会在这里更新。

相关问题