Post

Replies

Boosts

Views

Activity

Reply to @StateObject and view installation
I cannot provide exact repro steps as the bug is intermittent. But I can provide some general code as to how the StateObjects are used: import SwiftUI import Combine struct RootView: View {   private let columns: [GridItem] = [     GridItem(.flexible()),     GridItem(.flexible())   ]   var body: some View {     ScrollView {       LazyVGrid(columns: columns) {         ForEach(0..<20) { _ in           ContentView()         }       }     }   } } struct ContentView: View {   @StateObject   private var viewModel = ViewModel()       var body: some View {     content(viewModel.viewState)       .onAppear {         viewModel.subscribe()       }   }       @ViewBuilder   private func content(_ viewState: ViewState) -> some View {     switch viewState {     case .loading:       ProgressView()     case .content(let counter):       Text("\(counter)")         .padding()     }   } } extension ContentView {         enum ViewState: ObservableViewState {     case loading     case content(Int)           static var initialViewState: ViewState = .loading   }       enum Input {     case timerUpdated   }       enum Action {     case increment     case setState(ViewState)   }       class ViewModel: ObservableObject {     @Published     var viewState: ViewState = .loading     private let inputSubject = PassthroughSubject<Input, Never>()     private var subscribed = false     var internalInputPublisher: AnyPublisher<Input, Never> {       Timer.publish(every: 1, on: RunLoop.main, in: .common)         .autoconnect()         .eraseToAnyPublisher()         .map({ _ in           Input.timerUpdated         })         .eraseToAnyPublisher()     }           func subscribe() {       if subscribed {         return       }       subscribed = true       Publishers.Merge(internalInputPublisher, inputSubject)         .flatMap { input -> AnyPublisher<Action, Never> in           switch input {           case .timerUpdated:             return Just(.increment)               .eraseToAnyPublisher()           }         }         .scan(viewState, { currentState, action in           switch action {           case .setState(let state):             return state           case .increment:             if case .content(let counter) = currentState {               return .content(counter + 1)             } else {               return .content(1)             }           }         })         .removeDuplicates()         .assign(to: &$viewState)     }           func send(_ input: Input) {       inputSubject.send(input)     }   } } pretty much all view models follow this reactive publisher pattern for channeling view state updates to the listening view. The bug can happen to random views throughout the app
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Sep ’21