iOS 系统版本判断失效后的参数检查尝试

以下内容仅针对参数使用, 不包含方法检查。

以下内容仅针对OC, Swift不使用#available无法通过编译。

说明部分均为推测, 没有翻看汇编结果进行完备论证, 抛砖引玉。

通常来说, 遇到API_AVAILABLE限制版本的参数, 使用@available就能完成判断。

然而云谲波诡, 是时候确确实实发生了通过版本检查却访问变量崩溃的情况, 令人匪夷所思。

比如下面这个在网络类型判断中使用参数:

#import <CoreTelephony/CTTelephonyNetworkInfo.h>

CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyNRNSA         API_AVAILABLE(ios(14.1)) API_UNAVAILABLE(macos);

系统版本过低时, 直接调用会发生如下错误。

EXC_BAD_ACCESS (code=1, address=0x0)

最大的问题是, 即使通过了@available(iOS 14.1, *)的检查, 仍有可能在少数诡异的设备上崩溃。虽然不可思议, 但这是事实。

解法

if (&CTRadioAccessTechnologyNRNSA) {
    NSLog(@"1");
} else {
    NSLog(@"0");
}

对这些版本限制相关参数添加动态检查。

胡扯

一下内容均为我的脑补与胡扯, 缺乏严谨论证, 有待熟手指点。

一开始假设问题存在时, 任何显式访问CTRadioAccessTechnologyNRNSA的行为都会造成崩溃。

考虑到参数定义与内存对其。

CTRadioAccessTechnologyeHRPD
CTRadioAccessTechnologyLTE
CTRadioAccessTechnologyNRNSA
  • 指针还原

指针地址间隔相同。手动计算CTRadioAccessTechnologyNRNSA指针地址, 但是ARC下无法从内存地址直接还原NSString *指针, 失败。

  • memcmp

CTRadioAccessTechnologyNRNSA内容为@"CTRadioAccessTechnologyNRNSA", 既然知道目标地址, 直接通过内存比较内容?

不知道具体实现, 只能说可以比较一部分, 但没什么卵用, 尝试不出精确校验的方法, 失败。

  • 取地址

万念俱灰, 直接取地址。然鹅, 似乎可行。

盲猜是编译优化, 或者进程虚拟内存映射啥的, 反正似乎能用了。

posted @ 2022-01-29 20:41  Simon_X  阅读(267)  评论(0编辑  收藏  举报