Поведение объекта SwiftUI CurrentValueSubject

#swift #swiftui #combine

Вопрос:

Я новичок в SwiftUI. Я работаю с UIKit и объединяю фреймворк, создающий архитектуру с моделью представления, пользовательскими приложениями и репозиториями. Вся моя архитектура основана на состояниях загрузки. Мои состояния загрузки строятся таким образом:

 /// Equivalent to @Published with `LoadingStatelt;T, Egt;` property wrapper @propertyWrapper public class Loadinglt;T, E: Swift.Errorgt; { public typealias State = LoadingStatelt;T, Egt;  public var wrappedValue: State {  willSet {  subject.send(newValue)  } }  public init(wrappedValue: State) {  self.wrappedValue = wrappedValue }  private lazy var subject = CurrentValueSubjectlt;State, Nevergt;(wrappedValue)  public var projectedValue: AnyPublisherlt;State, Nevergt; {  return subject.eraseToAnyPublisher() } }  

и моя модель просмотра работает таким образом:

 @Loadinglt;MyData, MyErrorgt; var myDataLoadingState = .idle public func getMyData(ID: String) {  myDataLoadingState = .loading    myDataUseCase.execute(ID: ID)  .receive(on: DispatchQueue.main)  .sink { completion in  guard case .failure(let error) = completion else { return }  myDataLoadingState = .failure(error)  } receiveValue: { myData in  self. myDataLoadingState = .success(myData)  }  .store(in: amp;self.cancellables) }  

Контроллер работает таким образом:

 viewModel.$myDataLoadingState  .sink { state in  switch state {  case .idle:  break  case .loading:  self.showLoader()  case .success(let myData):  print(myData)  case .failure(let error):  self.print(error)  self.hideLoader()  }  }  .store(in: amp;cancellables)  

Могу ли я использовать состояние загрузки и мою модель представления в SwiftUI? Я пробовал таким образом, но, похоже, не работает:

 struct ContentView: View { @StateObject var viewModel: MyViewModel  var body: some View {  switch viewModel.loadingState {  case .idle:  Text("Idle")  case .loading:  Text("Loading")  case .success(let myData):  Text(myData.name)  case .failure(let error):  Text(error.localizedDescription)  } } }  

Модель представления теперь представляет собой ObservableObject

 public class MyViewModel: ObservableObject {  }  

Заранее спасибо

Комментарии:

1. У тебя myDataLoadingState есть @Published обертка?

2. ммм, нет. можете ли вы объяснить мне лучше?

Ответ №1:

Только что узнал , что у вас уже есть оболочка свойств myDataLoadingState , поэтому не уверен, что вам разрешено сделать это @Published вместо этого. В любом случае, чтобы сообщить @StateObject обертке (которая является слушателем), вы должны запустить событие об изменениях в модели представления. Возможный способ-использовать objectWillChange напрямую, например

 myDataUseCase.execute(ID: ID)  .receive(on: DispatchQueue.main)  .sink { completion in  guard case .failure(let error) = completion else { return }   self.objectWillChange.send() // lt;lt; here !!  myDataLoadingState = .failure(error)  } receiveValue: { myData in  self.objectWillChange.send() // lt;lt; here !!  self.myDataLoadingState = .success(myData)  }  .store(in: amp;self.cancellables)  

Комментарии:

1. ммм, хорошо, это решение! Спасибо! по вашему мнению, есть способ не редактировать каждую модель представления и напрямую использовать мое состояние загрузки?

2. Нет. Я не знаю, зачем вам это нужно, на самом деле все, что вам нужно, это @Published var myDataLoadingState .