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

求助:使用推送通知更新LiveActivities无响应问题

问题:Live Activity推送通知无更新响应

相关代码实现

启动LiveActivity方法

func startActivity(completion: @escaping (String) -> Void) {
        print("startActivity() is running")
        let attributes = PizzaDeliveryAttributes(numberOfPizzas: 2, totalAmount: "420", orderNumber: "359")

        let future = Calendar.current.date(byAdding: .minute, value: 35, to: Date())!.addingTimeInterval(40)
        let date = Date.now...future

        let initialContentState = PizzaDeliveryAttributes.ContentState(driverName: "Bill James", deliveryTimer:date)

        let activityContent = ActivityContent(state: initialContentState, staleDate: Calendar.current.date(byAdding: .minute, value: 30, to: Date())!)

        do {
            self.deliveryActivity = try Activity.request(attributes: attributes, content: activityContent, pushType: .token)
            print("Requested a pizza delivery Live Activity \(String(describing: self.deliveryActivity?.id)).")

            Task {
                for await data in self.deliveryActivity!.pushTokenUpdates {
                    let myToken = data.map {String(format: "%02x", $0)}.joined()
                    print("Token printed: \(myToken)")
                    completion(myToken)
                }
            }

        } catch (let error) {
            print("Error requesting pizza delivery Live Activity \(error.localizedDescription).")
        }
    }

更新状态方法

func updatePizzaDeliveryStatus(minutes: String, seconds: String) async {
        var future = Calendar.current.date(byAdding: .minute, value: (Int(minutes) ?? 0), to: Date())!
        future = Calendar.current.date(byAdding: .second, value: (Int(seconds) ?? 0), to: future)!
        let date = Date.now...future
        let updatedDeliveryStatus = PizzaDeliveryAttributes.PizzaDeliveryStatus(driverName: "Anne Johnson", deliveryTimer: date)
        let alertConfiguration = AlertConfiguration(title: "Delivery update", body: "Your pizza order will arrive in 25 minutes.", sound: .default)
        let updatedContent = ActivityContent(state: updatedDeliveryStatus, staleDate: nil)

        do {
            try await self.deliveryActivity?.update(updatedContent, alertConfiguration: alertConfiguration)
        } catch {
            print("Failed to update Live Activity: \(error)")
        }
    }

用于更新的CURL命令

curl -v \
--header "apns-topic:<Bundle-Id>.push-type.liveactivity" \
--header "apns-push-type:liveactivity" \
--header "authorization: bearer $AUTHENTICATION_TOKEN" \
--data \
'{"aps": {
   "timestamp":1663300480,
   "event": "update",
   "content-state": {
      "driverName": "Tony Stark",
      "deliveryTimer": {
        "start": 1663300480,       
        "end": 1663301480         
    }
   },
   "alert": {
      "title": "Race Update",
      "body": "Tony Stark is now leading the race!"
   }
}}' \
--http2 \
https://${APNS_HOST_NAME}/3/device/$DEVICE_TOKEN

ContentState定义

public struct ContentState: Codable, Hashable {
            var driverName: String
            var deliveryTimer: ClosedRange<Date>
        }

问题现状

已成功生成每个LiveActivity的pushToken,发送上述curl命令后无报错,但LiveActivity的动态内容未发生预期更新。

排查思路

  • 校验APNS主题格式:确认apns-topic中的<Bundle-Id>替换为实际App Bundle ID,格式必须严格为{BundleID}.push-type.liveactivity,无拼写错误。
  • 验证时间戳有效性:推送中的timestamp需为当前或未来的Unix时间戳,检查1663300480在发送推送时是否为有效时间(非过期时间)。
  • 修复ContentState序列化逻辑:Swift默认的ClosedRange<Date> Codable实现可能不匹配APNS要求,需手动实现编码确保日期转为Unix时间戳:
    public struct ContentState: Codable, Hashable {
        var driverName: String
        var deliveryTimer: ClosedRange<Date>
    
        enum CodingKeys: String, CodingKey {
            case driverName
            case deliveryTimer
        }
    
        public func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encode(driverName, forKey: .driverName)
            var timerContainer = container.nestedContainer(keyedBy: TimerCodingKeys.self, forKey: .deliveryTimer)
            try timerContainer.encode(Int(deliveryTimer.start.timeIntervalSince1970), forKey: .start)
            try timerContainer.encode(Int(deliveryTimer.end.timeIntervalSince1970), forKey: .end)
        }
    
        enum TimerCodingKeys: String, CodingKey {
            case start, end
        }
    }
    
  • 检查LiveActivity存活状态:确认deliveryActivity不为nil,且未超过staleDate进入终止状态,过期的LiveActivity无法接收更新。
  • 分析APNS响应日志:查看curl命令返回的响应码和内容,200 OK说明推送成功但客户端未处理;若为400 Bad Request等错误,根据提示调整推送内容。
  • 确认推送目标正确性:校验$DEVICE_TOKEN为当前设备有效token,$AUTHENTICATION_TOKEN是用正确密钥生成的、具备推送权限的APNS令牌。
  • 验证UI绑定逻辑:检查Widget的EntryView是否正确读取ContentState的driverName和deliveryTimer属性,确保UI层能响应状态变化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 04:22:41