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。
"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。