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

使用UserDefaults同步iOS与WatchOS数据的相关问题咨询

问题根因

你当前使用的UserDefaults.standard仅作用于当前应用的独立沙盒存储空间,iOS应用与WatchOS应用是两个独立的应用实体,默认沙盒完全隔离,因此两端存储的数据互不连通。
另外你现存代码还有逻辑问题:自定义类型[UserClass]无法直接存入UserDefaults,你已经实现了编解码方法,但代码中didSet和init的逻辑还是直接调用set(_:forKey:)和object(forKey:),会导致自定义类型存储失败,后续需要同步替换为编解码逻辑。

解决方案

下面提供两种常用的跨端同步方案,可根据需求选择:

方案1:App Groups 共享UserDefaults(适合小体量、非强实时需求的数据)

该方案通过苹果提供的App Groups能力让同一开发团队下的多个应用共享同一块存储空间,实现数据互通:

  • 打开Xcode,分别选中iOS端和WatchOS端的Target,进入「Signing & Capabilities」标签页,点击「+Capability」添加App Groups能力,两端添加完全相同的Group标识,格式为group.你的自定义标识,例如group.com.yourteam.classschedule
  • 替换代码中所有的UserDefaults.standard为共享Group的UserDefaults实例,参考修改:
import Foundation
import Combine

class UserSettings: ObservableObject {
    // 初始化共享UserDefaults,注意suiteName要和你配置的App Groups标识完全一致
    private let sharedDefaults = UserDefaults(suiteName: "group.com.yourteam.classschedule")!
    
    @Published var mon: [UserClass] {
        didSet {
            encodeClass(classes: mon, key: "mon")
        }
    }
    @Published var tue: [UserClass] {
        didSet {
            encodeClass(classes: tue, key: "tue")
        }
    }
    @Published var wed: [UserClass] {
        didSet {
            encodeClass(classes: wed, key: "wed")
        }
    }
    @Published var thu: [UserClass] {
        didSet {
            encodeClass(classes: thu, key: "thu")
        }
    }
    @Published var fri: [UserClass] {
        didSet {
            encodeClass(classes: fri, key: "fri")
        }
    }
    @Published var homeworks: [String] {
        didSet {
            sharedDefaults.set(homeworks, forKey: "homeworks")
        }
    }
    @Published var lastSet: String {
        didSet {
            sharedDefaults.set(lastSet, forKey: "lastSet")
        }
    }
    
    init() {
        self.mon = decodeClass(key: "mon")
        self.tue = decodeClass(key: "tue")
        self.wed = decodeClass(key: "wed")
        self.thu = decodeClass(key: "thu")
        self.fri = decodeClass(key: "fri")
        self.homeworks = sharedDefaults.object(forKey: "homeworks") as? [String] ?? []
        self.lastSet = sharedDefaults.object(forKey: "lastSet") as? String ?? ""
        print("homeworks \(homeworks)")
    }

    // 你原有编解码方法内部的UserDefaults也要替换为sharedDefaults
    func encodeClass(classes: [UserClass], key: String) {
        do {
            let encoder = JSONEncoder()
            let data = try encoder.encode(classes)
            sharedDefaults.set(data, forKey: key)
        } catch {
            print("Unable to Encode Array of Notes (\(error))")
        }
    }

    func decodeClass(key: String) -> [UserClass] {
        var classes: [UserClass] = []
        if let data = sharedDefaults.data(forKey: key) {
            do {
                let decoder = JSONDecoder()
                classes = try decoder.decode([UserClass].self, from: data)
            } catch {
                print("Unable to Decode Notes (\(error))")
            }
        }
        return classes
    }
}

struct UserClass: Hashable, Codable {
    let start: String
    let end: String
    let name: String
}
  • 注意:该方案的同步是由系统调度的,存在一定延迟,无法做到实时同步。

方案2:WatchConnectivity 框架同步(适合强实时、双向同步需求)

如果需要两端数据实时同步,可使用苹果官方的WatchConnectivity框架实现端到端数据传输:

  • 两端都导入WatchConnectivity框架,在UserSettings中初始化并激活WCSession,遵守WCSessionDelegate协议
  • 任意一端数据更新时,调用updateApplicationContext(_:)方法将最新数据同步给对端
  • 对端收到数据更新回调后,刷新本地存储和UI即可
注意事项
  • 两端的UserClass结构必须完全一致,否则会出现编解码失败问题
  • 若后续数据量增大,不推荐继续使用UserDefaults存储,建议替换为Core Data搭配App Groups,或者CloudKit实现多设备同步

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 00:45:04