3

在 ARC 下,我创建了一个分配给属性的 NSDictionary。然后我将其设置为 KVO 的 void* 上下文参数:

[obj addObserver:self 
      forKeyPath:kp 
         options:NSKeyValueObservingOptionNew 
         context:(void*)dict];

KVO 编程指南指出:

注意:键值观察 addObserver:forKeyPath:options:context: 方法不维护对观察对象、被观察对象或上下文的强引用。您应该确保根据需要维护对观察对象和观察对象以及上下文的强引用。

所以它没有强烈引用dict。我认为 ARC 对此没有问题,因为它只是一个论点。

当我收到回调时,我会像这样提取字典:

- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context {

    NSDictionary *dict = (__bridge NSDictionary*)context;
    //...

}

所以我记得有ARC 和 void*的问题,我认为当您将 void* 强制转换为 Objective-C 对象指针类型时使用 __bridge,而您不必在手动保留计数代码中调用-release 。因为我没有在这里创建所有权,所以我只是做 __bridge 所以 ARC 不会过度释放它。

但是我是否必须为 ARC 做一些特别的事情才能将字典设置为参数?Xcode 没有抱怨,但我感觉有些不对劲。

4

2 回答 2

0

基本上上下文不是为了传递一个对象,只是为了传递一个标识符(例如一个地址),以便可以识别特定的项目。

这与NSNotification可以传递声明为的对象不同:object:(id)anObject,而不是context:(void *)context

来自@nall的SO回答

当您注册通知时,您还可以指定上下文值。最后一个值就是返回给您的这个值。如果您没有任何特定于上下文的信息,则将 nil 传递给 addObserver: 是合适的。

参见:Mike Ash 谈“上下文”

于 2013-10-13T13:00:13.850 回答
0

我觉得你的基本假设是错误的,因为 arc 根本不关心 void * 并且你也没有传递对对象的引用(在这种情况下它只是一个指针)...... ARC 没有工作在那里做。

于 2013-10-13T19:36:55.200 回答