【问题标题】:Xcode12 compile error against Cocos3D: Incompatible block pointer typesXcode12 针对 Cocos3D 编译错误:块指针类型不兼容
【发布时间】:2021-01-04 11:36:58
【问题描述】:

“Xcode 12.0 (12A7209)”在以下代码中显示针对 Cocos3D 库(用 Objective-C 编写)的编译错误:
(Xcode的过去版本((即ver.11, 10),包括ver 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 在类型检查方面比以前的版本严格得多。

【问题讨论】:

    标签: objective-c objective-c-blocks cocos3d xcode12


    【解决方案1】:

    在 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 构建设置中。

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

    【讨论】:

    • 感谢您的回复,不胜感激。顺便说一句,你知道为什么这发生在 Xcode12 而不是其他“旧”版本(即 Xcode 11、10)中吗?也许在 Xcode12 中对 CLANG 进行了任何更改以使其类型检查比其他更严格?
    • 我认为这很有可能。编译器像任何其他软件一样发展并获得增强。所以这个检查可能最近被添加为一个新的“功能”。
    • 如果这解决了问题,你能接受这个答案,让其他人知道在哪里看吗?
    • 已经解决了这个问题,所以这个答案已经被采纳了。再次感谢。
    【解决方案2】:

    编辑稍微清理一下

    尝试添加

    -Wno-incompatible-pointer-types
    

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

    在 Xcode 中有一个选项,在 构建设置 > Apple Clang > 警告 > 所有语言 您会发现 将不兼容的指针类型视为警告。这不会让它静音,而是在警告或错误之间切换。

    【讨论】:

    • 感谢您回复我的帖子。顺便说一句,构建设置中的“将不兼容的指针类型警告视为错误”已被关闭,但出现编译错误。所以我猜,Xcode 的 Clang 或 SDK 在类型检查方面有一些变化。现在,无论如何我都可以通过更改块中的类型来构建二进制文件,正如我在更新中提到的那样。我已向苹果支持发送询问。如果我得到什么,我会发布它。谢谢。
    • 好的 - 感谢您的反馈......我理解 Clang 手册的方式应该将其关闭,我假设 Xcode 中提到的选项也是如此。如果不是,那么(新的)Xcode 可能有点太严格了。
    猜你喜欢
    • 2020-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多