如何从网络Service类更新ViewModel中的@Published变量?
解决方案:从Service更新ViewModel的@Published变量
针对你的需求,有几种常用的实现方式,能让Service类精准更新GenerationViewModel中对应的@Published变量,以下是具体实现:
方式一:使用SwiftUI Binding
利用@Published变量自带的$语法获取Binding实例,将其传入Service,直接通过Binding修改对应状态。
Service 实现
class Service { private let fetchingBinding: Binding<Bool> init(fetchingBinding: Binding<Bool>) { self.fetchingBinding = fetchingBinding } func performRequest() { // 标记请求开始 fetchingBinding.wrappedValue = true // 模拟异步网络请求 DispatchQueue.global().asyncAfter(deadline: .now() + 2) { // 请求结束,更新状态 self.fetchingBinding.wrappedValue = false } } }
ViewModel 调用
func go() { let service1 = Service(fetchingBinding: $fetching1) let service2 = Service(fetchingBinding: $fetching2) let service3 = Service(fetchingBinding: $fetching3) // 同时发起三个请求 service1.performRequest() service2.performRequest() service3.performRequest() }
方式二:使用闭包回调
如果不想依赖SwiftUI的Binding,可以通过闭包将状态更新逻辑传递给Service,请求状态变化时触发闭包更新ViewModel的变量。
Service 实现
class Service { private let updateStatus: (Bool) -> Void init(updateStatus: @escaping (Bool) -> Void) { self.updateStatus = updateStatus } func performRequest() { updateStatus(true) DispatchQueue.global().asyncAfter(deadline: .now() + 2) { self.updateStatus(false) } } }
ViewModel 调用
func go() { // 注意使用[weak self]避免循环引用 let service1 = Service(updateStatus: { [weak self] status in self?.fetching1 = status }) let service2 = Service(updateStatus: { [weak self] status in self?.fetching2 = status }) let service3 = Service(updateStatus: { [weak self] status in self?.fetching3 = status }) service1.performRequest() service2.performRequest() service3.performRequest() }
方式三:使用Combine Publisher
如果项目中使用Combine框架,可以让Service通过Publisher输出状态,ViewModel订阅后更新对应变量,适合复杂的异步状态流转场景。
Service 实现
import Combine class Service { private let statusSubject = PassthroughSubject<Bool, Never>() // 对外暴露只读的Publisher var statusPublisher: AnyPublisher<Bool, Never> { statusSubject.eraseToAnyPublisher() } func performRequest() { statusSubject.send(true) DispatchQueue.global().asyncAfter(deadline: .now() + 2) { self.statusSubject.send(false) } } }
ViewModel 调用
import Combine class GenerationViewModel: ObservableObject { @Published var fetching1:Bool = false @Published var fetching2:Bool = false @Published var fetching3:Bool = false // 存储订阅对象,防止被提前释放 private var cancellables = Set<AnyCancellable>() func go() { let service1 = Service() service1.statusPublisher .receive(on: DispatchQueue.main) // 切换到主线程更新UI状态 .assign(to: \.fetching1, on: self) .store(in: &cancellables) let service2 = Service() service2.statusPublisher .receive(on: DispatchQueue.main) .assign(to: \.fetching2, on: self) .store(in: &cancellables) let service3 = Service() service3.statusPublisher .receive(on: DispatchQueue.main) .assign(to: \.fetching3, on: self) .store(in: &cancellables) service1.performRequest() service2.performRequest() service3.performRequest() } }
各方式适用场景
- Binding方式:简单直接,适合纯SwiftUI项目,依赖SwiftUI框架。
- 闭包方式:无框架依赖,通用性强,适合UIKit与SwiftUI混合项目或跨模块场景。
- Combine方式:适合复杂状态管理场景,能处理多步异步流的状态传递,需要引入Combine框架。
内容的提问来源于stack exchange,提问作者erotsppa
相关产品推荐
相关产品推荐

