Custom view in SwiftUI reuse it in another view but need to have that view change properties of custom view like a button text color

I created a custom login view. I use that view within another view. I want the view using it to be able to set something like a color on a button. I tried doing this with passing color in the init and I was able to get that to work. This did not feel very much like swiftui style. I tried adding a method instead and calling the method and the code seems to run but does not actually change the color. My question is am I doing this correctly with the method and is that the best way or should I go back to using init or something else. Thanks.

Custom login view:
‘’’
public struct LoginView : View {
@ObservedObject var keyboardHandler: KeyboardFollower

@State var username: String = ""
@State var password: String = ""

@Binding var presentingLoginModal: Bool

@ObservedObject var userDefaultsManager = UserDefaultsManager()

let loginService: SoCoLoginService
let defaults = UserDefaults.standard
@State var loginTextButtonColor: Color = Color.blue

public init(loginService: SoCoLoginService, presentingLoginModal: Binding<Bool>) {
        self.keyboardHandler = KeyboardFollower()
        self.loginService = loginService
        self._presentingLoginModal = presentingLoginModal
    }

public var body: some View {
    VStack(content: {
        TextField("Username", text: $username)                
            .autocapitalization(UITextAutocapitalizationType.none).textFieldStyle(RoundedBorderTextFieldStyle())

        SecureField("Password", text: $password) {
            self.loginUser()
        }
            .autocapitalization(UITextAutocapitalizationType.none)
            .textFieldStyle(RoundedBorderTextFieldStyle())
        
        Button(action: self.loginUser) {
         HStack {
           Text("Log In")
             .font(.body)
             .bold()
             .foregroundColor(loginTextButtonColor)
         }
        }
        .disabled(username.isEmpty || password.isEmpty)
        .padding()
        
        Toggle(isOn: self.$userDefaultsManager.useFaceID) {
            Text("Use Face ID/Touch ID")
        }
    })
    .onAppear {
        if self.userDefaultsManager.useFaceID {
            let context = LAContext()
            context.localizedCancelTitle = "Enter Username/Password"
            var error: NSError?
            if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
                let reason: String
                if (context.biometryType == LABiometryType.faceID) {
                    reason = "Unlock using Face ID"
                } else if (context.biometryType == LABiometryType.touchID) {
                    reason = "Unlock using Touch ID"
                } else {
                    reason = "Log in to your account"
                }
                context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason ) { success, error in
                    
                    if success {
                        do {
                            let credentials = try self.loginService.getCredentialsInKeychain()
                            self.username = credentials.username
                            self.password = credentials.password
                            self.loginUser()
                        } catch KeychainError.unhandledError(let status) {
                          print("Unhandled error of: " + status.description)
                        } catch KeychainError.noPassword {
                          print("No password in keychain")
                        } catch {
                          print("Unexpected error.")
                        }
                    } else {
                        print(error?.localizedDescription ?? "Failed to authenticate")
                    }
                }
            }
        }
    }
    .padding(.bottom, keyboardHandler.keyboardHeight)
    .padding()
}

}

‘’’

my other view:
‘’’
struct ContentView: View {

@State var isScreenActive: Bool
@State var showingAlert: Bool

@EnvironmentObject var loginService: LoginService
@EnvironmentObject var userToken: UserToken

fileprivate func subscribeToToken() {
    _ = self.loginService.loginService.userToken
        .receive(on: DispatchQueue.main)
        .sink(receiveCompletion: {
            if case let .failure(error) = $0 {
                DDLogError("Error - ContentView - subscribeToToken: " + error.localizedDescription)
                self.showingAlert = true
            }
        }, receiveValue: { tokenResponse in
            print("user token is: " + tokenResponse.token)
            if case .none = tokenResponse.error {
                self.userToken.userToken = tokenResponse.token
                self.isScreenActive = true
            } else {
                //we did not get a token so user needs to try again
                let error = tokenResponse.error
                DDLogError("Error - ContentView - subscribeToToken: " + error.localizedDescription)
                self.showingAlert = true
            }
          
        })
        .store(in: &subscriptions)
}

var body: some View {
    NavigationView {
        VStack {
            Text("Hello World")
            LoginView(loginService: loginService.loginService,  presentingLoginModal: .constant(false)).setLoginButtonTextColor(Color.red)
            NavigationLink(destination: MainScreen(), isActive: self.$isScreenActive) {
                EmptyView()
            }
        }
        .alert(isPresented: $showingAlert) {
            Alert(title: Text("Error"), message: Text("There was an error with login, please try again."), dismissButton: .default(Text("OK")))
       }
        .navigationBarTitle("Login", displayMode: .inline)
        .onAppear() {
            self.subscribeToToken()
            MSAnalytics.trackEvent("Loaded login screen")
        }   
    }
}

}

‘’’

@directx Do you still have issues with this?

This topic was automatically closed after 166 days. New replies are no longer allowed.