You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS应用接收远程通知崩溃:Array._getElement问题排查与修复

排查与修复:FitSW App Store应用远程通知触发崩溃

问题场景

我负责的FitSW应用已经上线App Store,最近收到Xcode上报的崩溃日志,崩溃发生在应用接收远程通知的时候。日志里的关键栈帧指向:

Array._getElement(_:wasNativeTypeChecked:matchingSubscriptCheck:) + 12 (AppDelegate.swift:0)

一开始我完全找不到这个私有函数的相关代码,检查AppDelegate里的通知处理逻辑也没发现明显问题,而且不管怎么用模拟器测试,都没法复现这个崩溃。

触发崩溃的核心代码

崩溃对应的是application(_:didReceiveRemoteNotification:fetchCompletionHandler:)方法,原来的代码大概是这样:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    let notificationData = userInfo["data"] as? [String] ?? []
    let targetItem = notificationData[0]
    // 后续处理通知内容的逻辑
    completionHandler(.newData)
}

排查思路

  1. 解析崩溃栈:Array._getElement是Swift数组的私有底层函数,出现这个栈帧基本可以确定是数组越界访问导致的崩溃。
  2. 复现困境:模拟器测试时,我们发送的测试通知payload里data字段都是非空数组,所以没法触发;但生产环境中,部分通知的data字段是空数组,这时候直接访问[0]就会触发崩溃。
  3. 线程排查:另外发现通知回调可能在非主线程执行,某些情况下UI相关的操作会间接影响数组访问的稳定性。

最终修复方案

针对这两个问题,我做了两处修改:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    // 延迟到主线程执行,避免非主线程的潜在问题
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
        // 严格校验数组是否存在且非空
        guard let notificationData = userInfo["data"] as? [String], !notificationData.isEmpty else {
            completionHandler(.noData)
            return
        }
        let targetItem = notificationData[0]
        // 后续处理通知内容的逻辑
        completionHandler(.newData)
    }
}
  • 数组越界防护:用guard语句确保notificationData是有效数组且不为空,从根源避免越界访问。
  • 线程调度优化:通过DispatchQueue.main.asyncAfter延迟执行通知处理逻辑,保证在主线程且合适的时机执行,解决非主线程带来的潜在稳定性问题。

内容的提问来源于stack exchange,提问作者cmccune

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 10:45:28