iOS 15 CLLocation 读取 sourceInformation 崩溃

 原创    2024-04-25

在 iOS 15 之前,iOS 的 CoreLocation 库提供的定位信息并没有标示数据来源,比如可以通过在 iPhone 手机中插入外置 GPS 硬件,或通过蓝牙连接 GPS 外设等方式达到篡改原始 GPS 数据,而 CoreLocation 很难确切感知到 GPS 信息到底来自 iPhone 还是外部设备。

iOS 15 之后,Apple 终于开放了相关读取 GPS 信息来源的 API:

@interface CLLocationSourceInformation : NSObject <NSCopying, NSSecureCoding>

/*
 * isSimulatedBySoftware
 *
 * Discussion:
 * Set to YES if this location was detected as being generated by a software simulator, such as Xcode
 */
@property(readonly, nonatomic) BOOL isSimulatedBySoftware;

/*
 * isProducedByAccessory
 *
 * Discussion:
 *  Set to YES if this location was generated from an external accessory, such as CarPlay or an MFi accessory
 */
@property(readonly, nonatomic) BOOL isProducedByAccessory;
@end

CLLocation 新增 CLLocationSourceInformation 类型的 sourceInformation 属性,标识是软件生成的(isSimulatedBySoftware == true)还是 GPS 外设生成的(isProducedByAccessory == true)。示例代码如下:

if (@available(iOS 15.0, *)) {
    BOOL isSimulatedBySoftware = location.sourceInformation.isSimulatedBySoftware;
    BOOL isProducedByAccessory = location.sourceInformation.isProducedByAccessory;
}

但这个代码如果实际在线上运行,会发现存在部分的 iOS 15 设备直接 Crash 的情况:

-[CLLocation sourceInformation]: unrecognized selector sent to instance ...

问题的原因是,虽然 API 文档表明了这是一个在 iOS 15 及以上系统中可用的 API,但实际上是在 iOS 15 beta3 才开始生效的,这就导致上述代码运行在 iOS 15 beta1 或 iOS 15 beta2 系统上,就会产生找不到 sourceInformation selector 的崩溃。为了兼容这部分系统,改进的修复方案如下:

if (@available(iOS 15.0, *)) {
    if ([location respondsToSelector:@selector(sourceInformation)]) {
        BOOL isSimulatedBySoftware = location.sourceInformation.isSimulatedBySoftware;
        BOOL isProducedByAccessory = location.sourceInformation.isProducedByAccessory;
    }
}

不过话说回来,能使用 beta 系统且迟迟不更新的大概也不是正经用户吧😊。

相关文章:

iOS 13 中对 dyld 3 的改进和优化
iOS 真机和模拟器HTTPS Charles抓包指南
iOS安全:Tweak开发环境及入门
iOS 14 适配:更严格的用户隐私保护
分享 AppStore 审核的一些经验教训

发表留言

您的电子邮箱地址不会被公开,必填项已用*标注。发布的留言可能不会立即公开展示,请耐心等待审核通过。