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

Swift中如何让UserRepository的@Published属性随UserStorageService的@Published属性同步更新?

嘿,作为Swift新手能搭出这么清晰的分层架构已经很棒了!你的问题核心在于UserRepository没有监听UserStorageService的users变化,只是在fetch时做了一次性赋值,所以后续StorageService的数据更新无法同步到Repository,进而触发UI更新。我给你两种解决方案,按需选择:

方案一:用Combine订阅自动同步(推荐,适合需要处理数据转换的场景)

我们可以利用Combine框架订阅UserStorageService的@Published var users,每当它更新时自动同步到UserRepository的users属性。

修改UserRepository.swift代码:

import Combine

class UserRepository: RepositoryProtocol, ObservableObject {
    @Published var users: [User] = []
    @StateObject var userStorageService: UserStorageService
    // 用来保存订阅对象,防止被提前释放
    private var cancellables = Set<AnyCancellable>()

    init(dataController: DataController) {
        let storageService = UserStorageService(controller: dataController)
        _userStorageService = StateObject(wrappedValue: storageService)
        
        // 订阅StorageService的users变化,自动赋值给Repository的users
        userStorageService.$users
            .assign(to: \.users, on: self)
            .store(in: &cancellables)
    }

    func fetch() {
        // 这里不需要手动赋值了,订阅会自动同步
        try? userStorageService.fetch()
    }

    func add(data: User) throws {
        // 建议不要用try?吞掉错误,上层可以处理错误提示用户
        try userStorageService.add(data: data)
    }
}

方案二:直接代理StorageService的数据源(更简洁,适合无需数据转换的场景)

如果你的Repository不需要对原始数据做加工,可以直接让users成为计算属性,同时监听UserStorageService的变化信号,触发自己的objectWillChange通知:

import Combine

class UserRepository: RepositoryProtocol, ObservableObject {
    // 直接返回StorageService的users,无需自己维护数组
    var users: [User] { userStorageService.users }
    @StateObject var userStorageService: UserStorageService
    private var cancellables = Set<AnyCancellable>()

    init(dataController: DataController) {
        let storageService = UserStorageService(controller: dataController)
        _userStorageService = StateObject(wrappedValue: storageService)
        
        // 监听StorageService的变化,触发Repository的更新通知
        userStorageService.objectWillChange
            .sink { [weak self] _ in
                self?.objectWillChange.send()
            }
            .store(in: &cancellables)
    }

    func fetch() {
        try? userStorageService.fetch()
    }

    func add(data: User) throws {
        try userStorageService.add(data: data)
    }
}

额外注意事项

  1. 确保CoreData操作正确:在UserStorageService的add方法里,一定要保存上下文,否则NSFetchedResultsController不会检测到数据变化:
func add(data: User) throws {
    let newUser = User(context: dataController.container.viewContext)
    // 给新User赋值属性,比如newUser.name = data.name
    try dataController.container.viewContext.save()
}
  1. 错误处理:尽量避免用try?吞掉错误,应该把错误抛给上层ViewModel,让它处理错误状态(比如显示提示弹窗)。

这样修改后,当UserStorageService的users更新时,UserRepository会自动同步,进而触发ViewModel和View的更新啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 09:52:27