我正在进行一些代码重构,但面临一个问题,即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&lt;CommondProtocol&gt;'不可互换,正在寻找一种方法来推广此警告.有没有编译标志来实现这一点?

NOTE:我try 了'-Weverything',但它仍然没有显示转换警告.

推荐答案

这是Objective-C弱类型系统的自然结果,其中id几乎可以向下转换为任何类型的对象.用给定的协议专门化id在这方面没有多大帮助,这就是为什么您很容易遇到意外情况,比如当前的情况.

如果要强制转换,一种解决方案是将签名getObject更改为返回NSObject,而不是返回id:

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

此设置就绪后,naive Foo *casting = getObject();将生成一个明确的警告:

使用"NSObject*"类型的表达式初始化"Foo*"的指针类型不兼容

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

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

Objective-c相关问答推荐

如何以编程方式获取iphone的IP地址

应用程序终止时处理推送通知

当 UITextField 成为第一响应者时如何使 UIScrollView 自动滚动

通过指针算术访问数组值与 C 中的下标

UIAlertView 按钮操作

UIApplication.sharedApplication.delegate.window 和 UIApplication.sharedApplication.keyWindow 有什么区别?

声明变量id和NSObject *有什么区别?

NSMutableArray 判断对象是否已经存在

try 标记应用程序图标但未获得用户标记应用程序的权限:iOS 8 Xcode 6

Objective-C 中的 super 到底是什么?

我应该使用 NSUserDefaults 还是 plist 来存储数据?

在 NSArray 中查找最大数值

Objective-C 中的非正式协议?

嵌入自定义容器视图控制器时,内容位于导航栏下方.

-[MyClassName copyWithZone:] 无法识别的 Select 器发送到实例

如何像在 Spotify 的播放器中一样创建居中的 UICollectionView

在 DEBUG 模式下启用和禁用 NSLog

目标覆盖 FRAMEWORK_SEARCH_PATHS 构建设置

Instruments Allocations 跟踪用户定义类的对象的分配和解除分配

Xcode中私有方法的单元测试