Я использую Eureka SwitchRow для включения аутентификации FaceID / TouchID. Ход процесса выглядит следующим образом:
- Пользователь включает SwitchRow для включения FaceID / TouchID
- Бросить предупреждение, чтобы подтвердить включение, если подтверждено, выполнить аутентификацию
- В случае отмены , верните SwitchRow в предыдущее состояние
- Если аутентификация прошла успешно, сохраните настройки в UserDefaults, в противном случае верните SwitchRow в предыдущее состояние.
Проблема Как вернуться к предыдущее состояние без запуска onChange?
В этом посте здесь предлагается использовать следующий код:
form.delegate = nil
row.value = "Your value"
form.delegate = self
Но он не возвращает SwitchRow в предыдущее состояние. Он сохранил SwitchRow в новом состоянии, но отсоединяет onChange при повторном нажатии SwitchRow.
<<< SwitchRow() {
$0.title = "Enable FaceID/TouchID"
$0.value = false
}.onChange({ [weak form] in
if let form = form, let state = $0.value {
self.handleChange(state: state, switchRow: $0, form: form)
}
})
func handleChange(state: Bool, switchRow: SwitchRow, form: Form) {
//1. Throw alert to turn on
//2. if ok to turn on, authenticate
//3. Authenticated, save to userdefaults
let message = state ? "Are you sure you wanna enable?" : "Are you sure you wanna disable?"
let alert = UIAlertController(title: "Biometric unlock", message: message, preferredStyle: .alert)
let onOffAction = UIAlertAction(title: "Yes", style: .default) { (_) in
self.authenticateBiometric(state: state, switchRow: switchRow, form: form)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in
self.reset(fromState: state, switchRow: switchRow, form: form)
}
alert.addActions([onOffAction, cancelAction])
present(alert, animated: true, completion: nil)
}
func authenticateBiometric(state: Bool, switchRow: SwitchRow, form: Form) {
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Enable TouchID to unlock the app."
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { (success, error) in
if let error = error {
print("Error", error.localizedDescription)
self.reset(fromState: state, switchRow: switchRow, form: form)
return
}
if success {
if state {
//Turning on
print("Turning on successful")
} else {
//Turning off
print("Turning off successful")
}
UserDefaults.standard.set(state, forKey: "unlockWithBiometric")
UserDefaults.standard.synchronize()
} else {
print("Failed")
self.reset(fromState: state, switchRow: switchRow, form: form)
}
}
}
}
func reset(fromState: Bool, switchRow: SwitchRow, form: Form) {
DispatchQueue.main.async {
form.delegate = nil
switchRow.value = !fromState
form.delegate = self
}
}
Как можно вернуть switchRow обратно в предыдущее состояние, не вызывая onChange? Если onChange срабатывает, он перестанет работать на oop и начнет выдавать предупреждение снова и снова.