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

Swift中解析远程推送通知数据遇崩溃,求安全解析方案

iOS推送通知userInfo安全解析方案

兄弟,我太懂你这种解析推送userInfo时崩溃的糟心了!之前我也踩过类似的坑——直接强制类型转换或者解包,稍有不慎就触发崩溃。给你分享几个稳得一批的解析方法,再也不用担心翻车:

方法一:安全可选绑定+默认值(最直接)

这种方法不需要额外封装,每一步都做安全的类型校验,失败时给默认值,完全避免强制解包的风险:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    print("FFTF", "didReceiveRemoteNotification", userInfo)
    
    // 解析content-available(嵌套在aps字典中)
    let contentAvailable = (userInfo["aps"] as? [String: Any])?["content-available"] as? Int ?? 0
    
    // 解析FcmNotificationStatus
    let fcmNotificationStatus = userInfo["FcmNotificationStatus"] as? Int ?? 0
    
    // 解析ListItemIds(字符串数组)
    let listItemIds = userInfo["ListItemIds"] as? [String] ?? []
    
    // 解析UserId
    let userId = userInfo["UserId"] as? Int ?? 0
    
    // 后续业务逻辑使用这些字段
    print("contentAvailable: \(contentAvailable), fcmStatus: \(fcmNotificationStatus), listItemIds: \(listItemIds), userId: \(userId)")
    
    completionHandler(.newData)
}

为什么不会崩溃?

  • 用as?做安全类型转换,失败时会返回nil
  • 用??给nil情况设置默认值,保证变量始终有合法值
  • 嵌套字段先校验外层字典的存在,再取内层值,避免链式解包崩溃

方法二:用Codable模型化解析(更优雅易维护)

如果推送字段较多,或者后续需要频繁解析,推荐用Codable把数据模型化,代码可读性和维护性都会提升很多:

首先定义对应推送数据的结构体:

struct PushNotificationPayload: Codable {
    let aps: Aps
    let fcmNotificationStatus: Int
    let listItemIds: [String]
    let userId: Int
    
    // 处理aps内部的字段映射(推送里的content-available转成Swift驼峰命名)
    struct Aps: Codable {
        let contentAvailable: Int
        
        enum CodingKeys: String, CodingKey {
            case contentAvailable = "content-available"
        }
    }
    
    // 处理顶层字段的映射(和推送返回的字段名对应)
    enum CodingKeys: String, CodingKey {
        case aps
        case fcmNotificationStatus = "FcmNotificationStatus"
        case listItemIds = "ListItemIds"
        case userId = "UserId"
    }
}

然后在推送回调里解析:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    print("FFTF", "didReceiveRemoteNotification", userInfo)
    
    // 把userInfo转成Data,再用JSONDecoder解析成模型
    guard let jsonData = try? JSONSerialization.data(withJSONObject: userInfo, options: []),
          let payload = try? JSONDecoder().decode(PushNotificationPayload.self, from: jsonData) else {
        // 解析失败时的降级处理
        print("推送数据解析失败")
        completionHandler(.failed)
        return
    }
    
    // 成功解析后直接使用模型字段
    print("contentAvailable: \(payload.aps.contentAvailable), fcmStatus: \(payload.fcmNotificationStatus), listItemIds: \(payload.listItemIds), userId: \(payload.userId)")
    
    completionHandler(.newData)
}

避坑提醒

  • 绝对禁止用as!强制类型转换:哪怕你觉得字段肯定存在,服务器也可能出现版本变更、推送异常等情况,强制转换只会让崩溃找上门
  • 给字段设置合理默认值:比如Int类型用0,数组用空数组,避免nil导致的后续逻辑异常
  • 注意字段名大小写:推送返回的字段名和Swift里的命名要严格对应,或者用CodingKeys做映射

内容的提问来源于stack exchange,提问作者A.s.ALI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 17:52:29