2

我有几个用于一个 UIViewController 的数据源。我的视图控制器使用 KeyValue Observing 来跟踪运行时某些属性的状态。当我交换数据源时,我需要停止观察这些属性。问题是,我不确定运行时数据源的类,因此这样的事情是无效的:

if (aDataSource != dataSource) {
    // Ensure we stop observing the existing dataSource, otherwise bad stuff can happen.
    [dataSource removeObserver:self forKeyPath:@"someKeyPath"]; // not valid, compiler doesn't know what class dataSource is.
    [dataSource release];
    dataSource = [aDataSource retain];
}

编译器需要一个具体的类才能知道对象的接口。在这种特殊情况下,如何获取数据源的类,然后为上面的 removeObserver:forKeyPath: 选择器键入数据源?我更喜欢动态/更智能的东西,而不是在 NSString 实例中缓存类的名称并在我切换时引用它。意思是,我总是可以做类似的事情:

NSString *lastDataSource = @"MyClass";
Class foo = [NSClassFromString(lastDataSource)];

谢谢。

4

4 回答 4

6
  1. 如果你这样编码:

    id foo = ...;
    [foo removeObserver:self forKeyPath:@"someKeyPath"];
    

    编译器会很好,因为具有类型的对象id接受任何消息(只要编译器知道签名)。

  2. 现在,如果您有:

    id<NSObject> foo = ...;
    [foo removeObserver:self forKeyPath:@"someKeyPath"];
    

    编译器会给你一个警告:

    警告:'-removeObserver:forKeyPath:' 在协议中找不到

    这是因为您指的是协议 NSObject 而不是定义 KVO 方法的 NSObject 类。

  3. 但如果你有:

    NSObject* foo = ...;
    [foo removeObserver:self forKeyPath:@"someKeyPath"];
    

    这也可以很好地编译,因为在这种情况下您使用的是 NSObject 类。

相关链接:

于 2009-05-22T18:21:44.473 回答
2

你是什​​么意思它是无效的?你得到一个编译错误?

Objective-C 默认支持对象的动态类型。您应该能够在 Objective-C 中的任何对象上调用任何方法,即使编译器不能从静态类型保证该对象支持该方法。

于 2009-05-22T17:49:05.697 回答
1

我认为您需要将它们转换为NSObject *,因为那是 KVO 方法所在的位置(不在NSObject协议中)。

于 2009-05-22T18:10:48.483 回答
1

让我补充一下您概述的方法......

NSString *lastDataSource = @"MyClass";
Class foo = [NSClassFromString(lastDataSource)];

...当然无法抑制您的编译时警告,因为“foo”类只会在运行时计算。因此,即使您作为程序员可以从代码中清楚地看到“foo”最终将成为类“MyClass”,编译器也不清楚,所以如果“MyClass”有一个方法“myMethod:”,你会如果您将该消息发送到声明为“foo”的对象,仍然会收到编译器警告。

我猜你已经意识到了这一点,但最好弄清楚为什么这种方法不能解决你的问题。

于 2009-05-24T10:17:45.973 回答