【问题标题】:Cast object ( UIViewController ) to their unknown subclass将对象( UIViewController )转换为它们的未知子类
【发布时间】:2012-11-14 17:32:52
【问题描述】:

我开发了一个用于滑动 UIView 的通用控制器,并且我管理 UIViewController(显然是子类),并且只有当 UIViewController 的子类响应此方法时才必须调用特定方法(冻结):

-(void)freezeRootViewController
{
    if([_rootViewController respondsToSelector:@selector(freeze)])
        [ ((id) _rootViewController) freeze];
}

我不知道 _rootViewController 的类,但我知道它是 UIViewController 的子类,因此我尝试将我的 _rootViewController 转换为 ID,但我无法编译:

环境:XCode 4.5.1,带 ARC 的 iOs 4.3+

错误:“不知道选择器‘冻结’的实例方法”

注意:我不能强制开发人员为 _rootViewController 使用特定的 UIViewController 子类。

【问题讨论】:

  • 这不是警告而不是错误吗?
  • @H2CO3 不,XCode 4.5.1,带有 ARC 的 iOs 4.3+,不要编译。
  • 看我的回答,这应该会有所帮助(顺便说一句,把它变成一个错误是愚蠢的)。
  • 这也与Xcode的版本无关,也与clang/GCC的​​版本无关,似乎与使用的ARC有关。
  • 导入定义freeze方法的头文件。这会让编译器高兴。

标签: objective-c ios


【解决方案1】:

检查“通用”类型是否响应选择器后,如果它是简单的 0-1 参数方法,则使用 performSelector:/performSelector:withObject: 调用它,否则使用 NSInvocation。由于freeze 没有参数,您只需使用performSelector:

-(void)freezeRootViewController
{
    if([_rootViewController respondsToSelector:@selector(freeze)])
        [_rootViewController performSelector:@selector(freeze)];
}

【讨论】:

    【解决方案2】:

    这似乎是一个警告,而不是一个错误——您应该能够编译您的代码而忽略此诊断消息。但是,如果您想完全摆脱它,您可以声明一个协议并执行以下转换:

    @protocol MyProtocol <NSObject>
    
    - (void)freeze;
    
    @end
    
    [(id <MyProtocol>)_rootViewController freeze];
    

    【讨论】:

    • 不,这是一个错误,但如果我只将协议添加到我的课程中(没有演员表!!),一切都可以完美运行!谢谢;)
    • @Kappe 请接受/支持我的回答,谢谢。
    • @H2CO3:正如注释:使用 ARC,您无法编译未知方法选择器。参见例如lists.apple.com/archives/objc-language/2012/Jul/msg00114.html 据说这是故意决定将其设为错误而不是警告。
    • @MartinR 它仍然没有意义(顺便说一句,感谢您的链接)。如果方法返回id,编译器仍然可以发出强/弱引用;如果没有(或者如果返回值被强制转换),它不应该做任何事情。
    • 我不同意这种方法。 Kappe 检查了respondsToSelector:,因此应该使用performSelector:。在转换为协议之前,您应该检查它是否为conformsToProtocol:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-29
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 2013-09-03
    相关资源
    最近更新 更多