如何将KVO添加到同步类?

时间:2017-02-26 13:38:41

标签: ios objective-c key-value-observing kvocontroller

在我的应用中,我有Restaurant课程,您可以在下面看到。我想附上一个KVOController。但我没有运气。当我用下面的代码附上它时,它会崩溃。

FBKVOController *KVOController = [FBKVOController controllerWithObserver:self];
    self.KVOController = KVOController;

    [self.KVOController observe:self keyPath:@"[Restaurant current].name.asString" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew block:^(id observer, id object, NSDictionary *change) {
        DDLogDebug(@"Restaurant changed");
    }];

将KVO添加到这样的类中的最佳方法是什么?

@implementation Restaurant

static Restaurant *current = nil;

+ (Restaurant *)current {
    @synchronized(self) {
        if (current == nil) {            
            current = [[Restaurant alloc] initWithId:0];
        }
    }
    return current;
}

- (id)initWithId:(NSInteger)number {
    self = [super init];
    if (self)
    {
        ...
    }
    return self;
}

@end

1 个答案:

答案 0 :(得分:0)

问题不在于@synchronized。您的代码存在以下几个问题:

  • 您想观察当前餐厅的变化吗?或者当前餐馆的名称发生变化(没有+[Restaurant current]指向不同的餐馆实例)。或者是由current的更改或name的更改引发的任何类型的名称更改?
    • 根据答案,您要么想要observe:[Restaurant class]observe:[Restaurant instance],要求observe:self,除非您在Restaurant内进行设置类实现,在这种情况下[self class]可以替代[Restaurant class])。
    • 对于任何可观察的更改,您必须确保以KVO-compliant方式实现该类。这既适用于+[Restaurant current]的更改,也适用于-[Restaurant name]的更改,具体取决于您希望能够观察到的内容。
  • [Restaurant current].name.asString不是有效的密钥路径。有效的密钥路径可能只包含属性名称(ASCII,以小写字母开头,没有空格)和用于分隔它们的点(有关详细信息,请参阅Key-value coding)。一旦你告诉KVOController observe:[Restaurant class],关键路径的剩余部分就是current.name.asString
  • 如果不是字符串,name是什么?你真的需要将它转换成一个字符串来观察吗?如果您打算观察名称更改,则观察current.name可能就足够了。

您最终可能会遇到以下两种选择之一:

FBKVOController *kvoController = [FBKVOController controllerWithObserver:self];
[kvoController observe:[Restaurant class] keyPath:@"current.name" ...];`
// or
[kvoController observe:[Restaurant current] keyPath:@"name" ...];`

同样,对于任何可观察的变化,它们必须是KVO-compliant