为什么在UI中不更新此属性?

时间:2014-03-17 11:23:03

标签: objective-c cocoa binding key-value-observing

我有一个简单的应用:绑定到item.title的文本框。此属性公开为NSString,但内部为NSMutableString

问题:对title属性的更改未反映在用户界面中。

以下是item的实施:

@interface Item : NSObject
{
    NSMutableString *_title;
}

@property NSString *title;

@end

实施:

@implementation Item

-(void)mutateTitle
{
    [self willChangeValueForKey:@"title"];
    [_title appendString:@"mutated"];// this does not work
    //_title = [[NSMutableString alloc] initWithString:@"new instance"];// this works
    [self didChangeValueForKey:@"title"];
}

-(NSString *)title
{
    NSLog(@"get title returning: %@", _title);
    return _title;
}
-(void)setTitle:(NSString *)title
{
    _title = [[NSMutableString alloc] initWithString:title];
}

@end

按下按钮后,我们会向项目发送mutateTitle,这会更改标题,并通知KVO房产更改。

UI确实响应了更改,并且在调用title时,我们返回正确的字符串。

但是UI并没有反映出这些变化。

请注意,如果我取消注释我将新实例分配给_title的行,则更新正常。

此外,如果title返回_title副本,它也可以正常工作。

为什么会这样?有没有办法让我按照自己的意愿工作?


*编辑:title正在代码的其他地方分配;它不是nil

1 个答案:

答案 0 :(得分:1)

那是因为如果可变字符串发生变异,但属性没有改变(指针仍指向同一个对象),那么KVC将不会认为它是真正的变化。这可能是出于效率原因而做的(如果调用didChangeValueForKey:但字符串相同,则无需更新UI)。

我建议不要使用可变字符串,它不适合您的目的。只需使用普通字符串,而不是改变它重新分配它:

-(void)mutateTitle
{
    [self willChangeValueForKey:@"title"];
    _title= [_title stringByAppendingString: @"mutated"];
    [self didChangeValueForKey:@"title"];
}