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) } }
额外注意事项
- 确保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() }
- 错误处理:尽量避免用
try?吞掉错误,应该把错误抛给上层ViewModel,让它处理错误状态(比如显示提示弹窗)。
这样修改后,当UserStorageService的users更新时,UserRepository会自动同步,进而触发ViewModel和View的更新啦!
内容的提问来源于stack exchange,提问作者nzhmz
相关产品推荐
相关产品推荐

