简体   繁体   中英

Why my binding in ChildView does not update when ObservedObject updates?

This my code, when a user types in customTextField, username in ObservedObject viewmodel updates, but line if text.isEmpty in CustomTextField does not run. If I try to use testUsername by @State => it works. But I want to use ObservedObject, Can you help me? Thanks!

    struct CustomTextField: View {
            var placeholder: Text
            @Binding var text: String
            var editingChanged: (Bool)->() = { _ in }
            var commit: ()->() = { }
            
            var body: some View {
                ZStack(alignment: .leading) {
                    if text.isEmpty {
                        placeholder
                            .customPlaceHolderStyle()
                            .padding()
                    }
                    TextField("", text: $text, onEditingChanged: editingChanged, onCommit: commit)
                        .customTextFieldStyle()
                        .padding()
                }.background(Color.colorPrimaryDark)
                
            }
        }
    
    
    struct LoginView: View {
            @ObservedObject var viewModel : LoginViewModel
            
            @State var testUsername : String = ""
            
            var body: some View {
                BaseView(content: VStack(content: {
                    Image("logo_header")
                        .padding()
                    CustomTextField(placeholder: Text(NSLocalizedString("lb_username", comment: "")), text: $viewModel.username, commit:  {
                        UIApplication.shared.endEditing()
                    })
                    
                }).padding() , viewModel: viewModel)
            }
        }
    
    class LoginViewModel : BaseViewModel {
            private var authRepository: AuthRepository? = nil
            @Published var username : String = ""
            @Published var password : String = ""
            
            private init(authRepository : AuthRepository) {
                self.authRepository = authRepository
            }
            
            static let share : LoginViewModel = LoginViewModel(authRepository: AuthRepositoryImpl.share)
            
            
        }

The reason is in default publisher for ObservableObject which is generated for parent class. Assuming your BaseViewModel is-a ObservableObject , the solution for your case would be

class LoginViewModel : BaseViewModel {
        private var authRepository: AuthRepository? = nil
        
        var username : String = "" {
           willSet {  // in some cases didSet should be used
              self.objectWillChange.send()
           }
        }
        
        // do the same for 'password' property

As alternate you can try to combine publishers, like

class LoginViewModel : BaseViewModel {
    // ... other code

    override init() {
        super.init()
        _ = self.objectWillChange.append(super.objectWillChange)
    }
// ... other code

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM