Xcode12 针对 Cocos3D 的编译错误:不兼容的块指针类型

Xcode12 compile error against Cocos3D: Incompatible block pointer types

"Xcode 12.0 (12A7209)" 在以下代码中显示针对 Cocos3D 库(用 Objective-C 编写)的编译错误:
(Xcode 的过去版本((即版本 11、10),包括版本 11.7(11801a))没有这个问题,但 Xcode 12.0 有。)

错误信息:
不兼容的块指针类型将 'void (^)(CC3ShaderProgram *, BOOL *)' 发送到 'void (^)(id, BOOL *)'

类型的参数
// CC3Shaders.m
+(void) willBeginDrawingScene {
    [_programCache enumerateObjectsUsingBlock: ^(CC3ShaderProgram* prog, BOOL* stop) {
        [prog willBeginDrawingScene];
    }];
}

// CC3Cache.m
-(void) enumerateObjectsUsingBlock: (void (^) (id<CC3Cacheable> obj, BOOL* stop)) block {
    [self lock];
    [_objectsByName enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL* stop) {
        block([obj resolveWeakReference], stop);
    }];
    [self unlock];
}

基本上 Xcode 12.0 的 ObjC 编译器抱怨块“enumerateObjectsUsingBlock:”的输入参数的对象类型不匹配。

但是“CC3ShaderProgram”继承自“NSObject with CC3Cacheable protocol”如下:

@interface CC3ShaderProgram : CC3Identifiable 
@interface CC3Identifiable : NSObject <CC3Cacheable, NSCopying>

因此,“CC3ShaderProgram”是与“id”匹配的类型,因此编译器不应该抱怨,但 Xcode12.0 会。

不仅在“willBeginDrawingScene”,而且在库中使用“enumerateObjectsUsingBlock:”的其他地方也有同样的问题。

过去几年我一直在使用 Cocos3D 库和几个不同版本的 Xcode 没有这个问题。

“Xcode 12.0”的 CLANG 或 SDK 是否有任何更改以在块参数类型检查方面变得更严格(例如“不允许使用通用对象指针”id“)?否则,我不明白为什么这两个匹配的类型会被编译器认为是不匹配的类型,导致在Xcode 12.0.

中出现编译错误

请问您能提供什么好的解决方案吗?将不胜感激。

谢谢。

更新: 在更改参数类型以在块中包含“NSCopying”协议后(使参数类型的协议设置与“CC3ShaderProgram”相同),Xcode12 编译器已停止抱怨。 (以前,仅包含 CC3Cacheable 协议。)

-(void) enumerateObjectsUsingBlock: (void (^) (id<CC3Cacheable, NSCopying> obj, BOOL* stop)) block

目前,代码二进制构建没有此编译错误。但是,我仍然不明白为什么 Xcode 12.0 会抱怨这个,除非 Xcode12 的 CLANG 在类型检查方面比以前的版本严格得多。

编辑 清理了一下

尝试添加

-Wno-incompatible-pointer-types

您的编译器标志(构建设置 > Apple Clang > 自定义编译器标志 > 其他警告标志)。这是最好且非常有用的选项,因为它可以消除这个通常令人讨厌的警告。

在 Xcode 中有一个选项,在 Build Settings > Apple Clang > Warnings > All languages 你'会发现 Treat incompatible pointer types as warnings。虽然这不会使其静音,但会在警告或错误之间切换。

在 Cocos3D 中有两种方法可以解决这个问题。

可以在CC3Cache.h中的代码中修复,通过在[CC3Cache enumerateObjectsUsingBlock:]的定义中添加__kindof如下:

-(void) enumerateObjectsUsingBlock: (void (^) (__kindof id<CC3Cacheable> obj, BOOL* stop)) block;

这是应该修复的地方。

或者,可以在构建时消除错误,无需更改代码,方法是:

-Xclang -fcompatibility-qualified-id-block-type-checking

OTHER_CFLAGS 构建设置中。

可以找到这些解决方案的原始来源 here and here