分配时检查块签名不一致

时间:2013-12-09 02:38:52

标签: objective-c objective-c-blocks

我有一个带有block属性的类,用于配置表视图单元格:

    typedef void(^MyBlockDef)(UITableViewCell *cell, NSIndexPath *indexPath);

    @interface MyClass : NSObject
    @property (nonatomic, copy) MyBlockDef foo;
    @end

并按照您的预期分配给该物业:

    obj.foo = ^(UITableViewCell *cell, NSIndexPath *indexPath) {
        MyTableViewCell *myCell = (MyTableViewCell *)cell;
        // configure myCell...
    };

但是,在块中我总是需要在我想配置它时将cell参数强制转换为我的子类。我更喜欢在块签名中指定我的单元子类,当我知道它将是特定类型时:

    obj.foo = ^(MyTableViewCell *cell, NSIndexPath *indexPath) {
        // configure cell...
    };

但是当我这样做时,编译器会抱怨:

    error: incompatible block pointer types assigning to 'MyBlockDef' (aka 'void (^)(UITableViewCell *__strong, NSIndexPath *__strong)') from 'void (^)(MyTableViewCell *__strong, NSIndexPath *__strong)'

有没有解决方法,或者我可以关闭一些检查?我完全理解为什么它认为这是一个错误,但是因为当block参数被指定为id时编译器没有抱怨它只是看起来有点不一致:

    obj.foo = ^(id cell, NSIndexPath *indexPath) {
      MyTableViewCell *myCell = (MyTableViewCell *)cell;
      // configure myCell...
    };

思考?感谢。

1 个答案:

答案 0 :(得分:2)

当您尝试转换继承树(朝向更具体的子类)时,编译器不喜欢它,因为静态分析器无法保证转换目标的接口与您说的类型兼容。块签名比对象需要更多的关注,因为它们必须关心它们的参数类型,因为它确定了捕获语义。由于其类型中立性,您可以使用id来消除警告。这并不是不一致的,而是向您展示“选择退出”类型安全的结果。您可以使用UITableViewCell签名进行相同的投射,然后干净利落。请勿关闭警告,将typedef调整为更具体,或在必要时调整id更通用或投射必要参数。