#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
.