Clang:为像 id<protocol> 到 class<Protocol> 这样的类型转换提供警告?

Clang: promoting warning for type-casting like id<protocol> to class<Protocol>?

我正在做一些代码重构,但遇到一个问题,clang对这种情况没有任何警告:

@protocol CommonProtocol <NSObject>
- (void)common;
@end
=========
@interface Foo : NSObject <CommonProtocol>
- (void)foo;
@end
=========
@interface Bar : NSObject <CommonProtocol>
@end
=========
static id<CommonProtocol> getObject(void) {
    return [Bar new];
}

Foo *casting = getObject(); /// ⚠️ there is no warning for this
[casting common];
[casting foo]; ///  crash because the casting object do not respond to '-foo'

我认为类型 'Foo *' 和 'id<CommondProtocol>' 不可互换,正在寻找一种方法来推广此警告。任何编译标志来实现这个?

注意: 我已经尝试了 '-Weverything',它仍然没有显示转换警告。

这是 Objective-C 弱类型系统的自然结果,其中 id 实际上可以向下转换为任何类型的对象。专门 id 使用给定的协议在这个方向上没有多大帮助,这就是为什么你可以轻松地 运行 进入意外情况,比如当前的情况。

如果您想强制转换,一种解决方案是将 getObject 的签名更改为 return NSObject 而不是 id:

static NSObject<CommonProtocol> *getObject(void) {
    return [Bar new];
}

有了这个设置,天真的 Foo *casting = getObject(); 将生成一个明确的警告:

Incompatible pointer types initializing 'Foo *' with an expression of type 'NSObject *'

,编写代码的人必须显式转换:

Foo *casting = (Foo *)getObject();