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

WatchOS Complication读取共享UserDefaults为nil问题求助

问题:Watch Complication无法读取App Group共享的UserDefaults数据

已实现iPhone通过WCSession的ApplicationContext将数据写入共享App Group的UserDefaults,Watch主应用可以正常读取这些数据,但Watch Complication读取同一App Group的UserDefaults时,所有值都返回nil。已确认Complication所在的Watch Extension已开启对应App Group权限,也尝试过重新添加App Group、创建新组,问题依旧。

iPhone端接收并写入共享UserDefaults的代码

func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
    let defaults = UserDefaults(suiteName: K.appGroupID)
    
    if let value1 = applicationContext["lat"] as? Double {
        defaults?.setValue(value1, forKey: "lat")
    }
    if let value2 = applicationContext["lng"] as? Double {
        defaults?.setValue(value2, forKey: "lng")
    }
}

Complication端读取代码(返回nil)

func sunsetTime() -> String {
    let formatter = DateFormatter()
    formatter.timeStyle = .short
    formatter.timeZone = .current
    
    let defaultLoad = UserDefaults.init(suiteName: K.appGroupID) 
    if defaultLoad!.bool(forKey: "timeFormat") == true { // 此处读取值为nil
        // ... 后续逻辑
    }
    // ... 返回结果
}

解决步骤

1. 确认Complication Extension的App Groups配置完全正确

  • 打开Xcode,选中Complication对应的Extension target,进入Signing & Capabilities标签页
  • 确认App Groups已添加,且Group ID和Watch主应用、iPhone应用完全一致(格式如group.com.yourcompany.yourapp)
  • 检查Extension的Info.plist中是否存在com.apple.security.application-groups键,且值包含目标Group ID,若缺失需手动添加

2. 写入UserDefaults时强制同步

Watch主应用写入共享数据后,调用synchronize()确保数据立即持久化到共享容器,避免Complication读取到缓存的空数据:

func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
    guard let defaults = UserDefaults(suiteName: K.appGroupID) else { return }
    
    if let value1 = applicationContext["lat"] as? Double {
        defaults.set(value1, forKey: "lat")
    }
    if let value2 = applicationContext["lng"] as? Double {
        defaults.set(value2, forKey: "lng")
    }
    defaults.synchronize() // 强制同步到共享容器
}

3. 修复Complication中的读取逻辑

避免强制解包UserDefaults实例,同时为读取操作设置默认值,防止nil问题:

func sunsetTime() -> String {
    let formatter = DateFormatter()
    formatter.timeStyle = .short
    formatter.timeZone = .current
    
    guard let defaultLoad = UserDefaults(suiteName: K.appGroupID) else {
        print("无法初始化共享UserDefaults")
        return "N/A"
    }
    // 读取时传入默认值,避免nil判断异常
    let is24HourFormat = defaultLoad.bool(forKey: "timeFormat")
    if is24HourFormat {
        // ... 后续逻辑
    }
    // ... 返回结果
}

4. 给Complication添加数据请求 fallback 方案

Complication可能在Watch主应用未启动时运行,此时可以通过WCSession主动向主应用请求数据:

// 在Complication控制器中实现数据请求逻辑
if WCSession.isSupported() {
    let session = WCSession.default
    session.delegate = self
    session.activate()
    session.sendMessage(["requestSync": true], replyHandler: { replyData in
        guard let defaults = UserDefaults(suiteName: K.appGroupID) else { return }
        // 将主应用返回的数据写入共享容器
        if let lat = replyData["lat"] as? Double {
            defaults.set(lat, forKey: "lat")
        }
        if let lng = replyData["lng"] as? Double {
            defaults.set(lng, forKey: "lng")
        }
        defaults.synchronize()
    }, errorHandler: { error in
        print("请求主应用数据失败:\(error.localizedDescription)")
    })
}

同时在Watch主应用的WCSessionDelegate中处理该请求:

func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
    if message["requestSync"] != nil {
        guard let defaults = UserDefaults(suiteName: K.appGroupID) else {
            replyHandler([:])
            return
        }
        // 返回当前共享容器中的数据
        let reply = [
            "lat": defaults.double(forKey: "lat"),
            "lng": defaults.double(forKey: "lng"),
            "timeFormat": defaults.bool(forKey: "timeFormat")
        ]
        replyHandler(reply)
    }
}

5. 清理环境重新部署

  • 删除iPhone和Watch设备上的应用
  • 执行Product > Clean Build Folder清理Xcode缓存
  • 重新构建并部署到设备,确保所有target的签名和Capabilities配置完全同步

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 16:35:22