Я создал пользовательский вид входа в систему. Я использую это представление в другом представлении. Я хочу, чтобы вид, использующий его, мог установить что-то вроде цвета на кнопке. Я попытался сделать это с передачей цвета в init, и я смог заставить это работать. Это не очень похоже на стиль Swiftui. Вместо этого я попытался добавить метод и вызвать метод, и кажется, что код работает, но фактически не меняет цвет. Мой вопрос заключается в том, правильно ли я делаю это с помощью метода, и является ли это наилучшим способом или я должен go вернуться к использованию init или чего-то еще. Спасибо.
Пользовательский вид входа в систему: '' 'publi c struct LoginView: Просмотр {@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()
}
}
' ''
мое другое представление: '' 'struct ContentView: представление {
@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")
}
}
}
}
' ''