KVO使用NSMutableArray

时间:2011-08-07 23:41:41

标签: objective-c

我的AppDelegate中有一个名为blocks的NSMutableArray属性。 每当一个对象被添加到这个数组时我想观察。 我读过其他帖子,但我不明白为什么这不起作用。

在我的app委托类中,我实现了

- (void)insertObject:(id)obj inBlocksAtIndex:(NSInteger)index
{
    [blocks insertObject:obj atIndex:index];
}

在我的视图控制器的init方法中,我向AppDelegate引用添加了一个观察者。

boardModel = [[UIApplication sharedApplication] delegate];
[boardModel addObserver:self forKeyPath:@"blocks" options:0 context:NULL];

在我的视图控制器的viewDidLoad方法中,我尝试调用我之前实现的KVO索引数组访问器,

[boardModel insertObject:[[Block alloc] init] inBlocksAtIndex:0];

然后我实现了observeValueForKeyPath方法:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"blocks"])
    {
        NSLog(@"ADDED");
    }
}

我已经尝试在observeValueForKeyPath中的if语句之前添加一个NSLog语句,似乎它永远不会被调用。

我也尝试了NSLogging [[boardModel blocks] count],它说计数为1(正在添加对象)。

我一定错过了什么。

5 个答案:

答案 0 :(得分:12)

问题是NSArray不尊重KVO,因此观察密钥路径计数将不起作用。

如果这是MacOSX,请使用NSArrayController。否则为数组创建一个包装类,在添加/删除数组内容时触发KVO调用,并传递所有其他调用。

答案 1 :(得分:1)

你试过吗

   - (void)insertObject:(id)obj inBlocksAtIndex:(NSInteger)index
    {
        [[self mutableArrayValueForKey:@"blocks"] insertObject:obj atIndex:index];
     }

答案 2 :(得分:0)

您正在观察应用委托的blocks属性,而不是blocks数组本身。希望以下示例能够明确区分:

// This will fire KVO as you're changing the app delegate's `blocks` property.
appDelegate.blocks = [NSMutableArray array];

// This will not fire KVO as the app delegate's `blocks` property still points
// to the same object; from the app delegate's perspective, nothing's happened.
[appDelegate.blocks addObject:@"Object"];

如果您希望在blocks数组的内容发生更改时收到通知,请观察数组本身的属性 - 类似count。更新您的代码:

[boardModel.blocks addObserver:self forKeyPath:@"count" options:0 context:NULL];

答案 3 :(得分:0)

我只是开源了一个非常小的Objective-C库,它为NSMutableArray添加了一个委托。它可能会帮助您实现您想要做的事情。查看FCMutableArray on GitHub

答案 4 :(得分:0)

并非NSMutableArray在某些方面不符合KVO标准,所有符合KVO标准的属性必须是NSObjects。 "计数"是一个NSUInteger;你不能直接观察那个属性。如果它是NSNumber对象,你可以。

来自NSArray头文件:

@interface NSArray<__covariant ObjectType> : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>

@property (readonly) NSUInteger count;

顺便问一下,为什么接受答案?很明显,回答者没有测试他的答案。