如何在运行时动态地将id类型转换为具体类?

2 iphone cocoa dynamic objective-c key-value-observing

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

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];
}
Run Code Online (Sandbox Code Playgroud)

编译器需要一个具体的类才能知道对象的接口.如何在这种特殊情况下获取dataSource类,然后为上面的removeObserver:forKeyPath:selector打印dataSource?我更喜欢动态/更聪明的东西,而不是在NSString实例中缓存类的名称,并在每次切换时引用它.意思是,我总是可以这样做:

NSString *lastDataSource = @"MyClass";
Class foo = [NSClassFromString(lastDataSource)];
Run Code Online (Sandbox Code Playgroud)

谢谢.

mfa*_*kas 6

  1. 如果您这样编码:

    id foo = ...;
    [foo removeObserver:self forKeyPath:@"someKeyPath"];
    
    Run Code Online (Sandbox Code Playgroud)

    编译器可以正常使用它,因为具有类型的对象id接受任何消息(只要编译器知道签名).

  2. 现在,如果你有:

    id<NSObject> foo = ...;
    [foo removeObserver:self forKeyPath:@"someKeyPath"];
    
    Run Code Online (Sandbox Code Playgroud)

    编译器会给你一个警告:

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

    这是因为您指的是协议NSObject而不是NSObject类,其中定义了KVO方法.

  3. 但如果你有:

    NSObject* foo = ...;
    [foo removeObserver:self forKeyPath:@"someKeyPath"];
    
    Run Code Online (Sandbox Code Playgroud)

    那也可以正常编译,因为在这种情况下你使用的是NSObject类.

相关链接: