Swift中`#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140500`的等价写法,低版本Xcode适配咨询
Swift 对应 OC 版本判断宏的等价实现
OC里常用的这两个宏,本质都是编译时判断当前打包用的SDK是否包含高版本API的定义,和日常写的运行时判断用户设备系统版本的逻辑完全不是一回事。Swift没有单独造一套全新的判断语法,两种等价实现都可以直接用:
- 对应
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140500的写法:Swift的条件编译块可以直接读取Clang暴露的同名SDK版本宏,直接写同样的代码就行,判断逻辑完全一致,绝大多数主流Xcode版本都能正常编译通过。 - 对应
#ifdef __IPHONE_14_5的写法:这个OC宏只是用来标记SDK里有没有定义iOS14.5的版本枚举值,Swift端没必要单独判断这个宏存不存在,上面的版本数值判断已经完全覆盖了它的作用,多写反而冗余。
低版本Xcode下编译SKAdImpression代码的适配方案
这类编译问题根本原因很简单:SKAdImpression是iOS14.5(对应Xcode12.5及以上)才在StoreKit里新增的类,低版本Xcode自带的SDK里压根没有这个类型的定义。哪怕之前在高版本Xcode里写了运行时的if #available(iOS 14.5, *)判断也没用——编译器在语法解析阶段就因为找不到这个类型直接抛错,根本走不到运行判断的逻辑。适配的时候按下面的步骤走就行:
- 首先把所有直接引用SKAdImpression类的代码,全部用前面说的编译时版本判断块包起来,保证低版本SDK编译时,这部分碰新API的代码根本不会被纳入编译链路,从根源上避免找不到类型的报错。
- 其次要给低版本SDK环境补一套同接口的空实现,不然上层业务代码调用这些方法的时候,还是会因为类型不存在报错,参考写法:
import StoreKit #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140500 // 高版本SDK下直接用系统原生的SKAdImpression能力 class AdImpressionReporter: NSObject, SKAdImpressionDelegate { // 这里写原本的曝光上报业务逻辑就行 } #else // 低版本SDK下提供一模一样的类名和方法名的空实现 class AdImpressionReporter: NSObject { func reportImpression(_ model: Any) { // 没有实际逻辑,只是保证类型能被识别 } } #endif - 如果碰到极老版本的Xcode,连Swift块里直接读
__IPHONE_OS_VERSION_MAX_ALLOWED宏都报语法错,就用最稳妥的兜底方案:在项目的OC桥接头文件里写个标记宏,再拿到Swift端用:
桥接头文件里的OC代码:
Swift端直接写#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140500 #define CAN_USE_SKAD_IMPRESSION 1 #else #define CAN_USE_SKAD_IMPRESSION 0 #endif#if CAN_USE_SKAD_IMPRESSION就能完成同样的条件编译,这个写法对老Xcode的兼容性是最高的。
特别提醒:跨Xcode版本适配最容易踩的坑就是把新API代码全塞在
if #available(iOS 14.5, *)的运行时判断块里。这个语法只负责在用户运行APP的时候判断系统版本,挡不住低SDK下类型不存在的编译错误,别白费功夫。
内容的提问来源于stack exchange,提问作者hezhk3
相关产品推荐
相关产品推荐

