iOS 16 Binding issue (in this case Toggle)

Viewed 24

What i have stumped across is that when i pass a Binding<> as a parameter in a ViewModel as you will see below, it doesn't always work as intended. It works in iOS 15 but not in iOS 16. This reduces the capability to create subviews to handle this without sending the entire Holder object as a @Binding down to it's subview, which i would say would be bad practice. So i have tried to minimize this as much as possible and here is my leasy amount of code to reproduce it:

import SwiftUI

enum Loadable<T> {
    case loaded(T)
    case notRequested
}

struct SuperBinder {
    let loadable: Binding<Loadable<ContentView.ViewModel>>
    let toggler: Binding<Bool>
}

struct Holder {
    var loadable: Loadable<ContentView.ViewModel> = .notRequested
    var toggler: Bool = false
    
    func generateContent(superBinder: SuperBinder) {
        superBinder.loadable.wrappedValue = .loaded(.init(toggleBinder: superBinder.toggler))
    }
}

struct ContentView: View {
    
    @State var holder = Holder()
    
    var superBinder: SuperBinder {
        .init(loadable: $holder.loadable, toggler: $holder.toggler)
    }
    
    var body: some View {
        switch holder.loadable {
        case .notRequested:
            Text("")
                .onAppear(perform: {
                    holder.generateContent(superBinder: superBinder)
                })
        case .loaded(let viewModel):
            Toggle("testA", isOn: viewModel.toggleBinder) // Works but doesn't update UI
            Toggle("testB", isOn: $holder.toggler) // Works completly
            // Pressing TestA will even toggle TestB
            // TestB can be turned of directly but has to be pressed twice to turn on. Or something?
        }
    }
    
    struct ViewModel {
        let toggleBinder: Binding<Bool>
    }
}

anyone else stumbled across the same problem? Or do i not understand how binders work?

0 Answers
Related