Автозаполнение работает невероятно хорошо, но у меня есть один сценарий, когда он не оптимален, и я не знаю, как можно обойтись, возможно, правильным способом сделать это.
У меня есть экран с двумя UITextFields, первое - Amount, денежное выражение, которое нужно передать другому человеку. Второе поле - это пароль, пользователю нужно будет повторно ввести свой пароль, прежде чем транзакция может быть завершена.
Первое поле (количество) имеет тип содержимого, установленный как .unspecified, а второе поле (пароль) имеет значение .password.
Когда пользователь нажимает второе поле Автозаполнение красиво предлагает пароль, который будет использоваться, но как только правильный пароль будет нажат, iOS автоматически предполагает, что первое поле (сумма) является именем пользователя и заполняет его именем пользователя, связанным с выбранной учетной записью, перезаписывая сумма, которую пользователь ранее ввел.
Есть ли способ заставить пароль только автозаполнение?
Установите его на UITextContentType("unspecified")
ИЛИ .oneTimeCode
lol
Я сделал, независимо от того, что я его установил, он все равно получает назначенное ему имя пользователя. Скрытое текстовое поле, установленное на имя пользователя, было бы решением, хотя, на мой взгляд, немного взломанным. Говоря о хакерском решении, я сейчас использую UITextFieldDelegate с textFieldDidEndEditing. В первый раз, если поле является двойным, я сохраняю его в памяти, во второй раз, после того, как оно получит имя пользователя, если поле не двойное, я присвоил значение, хранящееся в памяти. Я скомпилирую ответ всеми этими методами, но я немного подожду, пока, возможно, кто-нибудь не получит правильный ответ.
Сегодня я столкнулся с той же проблемой, но по-другому. Моя ситуация заключается в вводе записей mobile number
и password
на страницу входа. Собственное приложение поддерживает только номер мобильного телефона, а веб-приложение поддерживает только email
. Таким образом, пока действует автозаполнение iOS, оно заполняет поле номера мобильного телефона полем email
, что недопустимо.
Поиграв некоторое время с автозаполнением, я обнаружил, что жизненный цикл делегата UITextField
несколько отличается в случае автозаполнения.
При нажатии на автозаполнение, которое предусмотрено в верхней части клавиатуры, UITextFieldDelegate
начинает работать с самого начала. Хотя клавиатура открыта, метод делегата запускается из текущего с порядком вызовов следующим образом
textField(_:shouldChangeCharactersIn:replacementString:)
textFieldShouldEndEditing(_:)
Этот делегат вызывает без отключения клавиатуры и снова появляется. Это необычно. Возврат false
в textField(_:shouldChangeCharactersIn:replacementString:)
в этом случае не имеет никакого эффекта.
Так что теоретически у меня есть возможность редактировать mobile field
в textFieldShouldEndEditing
. Для этого я отслеживаю текст, который присутствовал до начала автозаполнения. поэтому взял две переменные следующим образом
var previousText: String?
var nextText: String?
Каждый раз, когда UITextField
начинает редактирование, я сохраняю его в previousText
следующим образом
public func textFieldDidBeginEditing(_ textField: UITextField) {
previousText = textField.text
}
затем я отслеживаю изменения внутри textField(_:shouldChangeCharactersIn:replacementString:)
следующим образом
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
nextText = self.getCompleteString(original: textField.text, replacingRange: range, withString: string)
// YOU MAY RETURN `true` OR `false` BASED ON KEYBOARD TYPING, BUT RETURNING `false` IN CASE OF AUTOFILL HAS NO EFFECT. SO I ASSUME, YOU RETURN `true` ALWAYS.
return true;
}
func getCompleteString(original: String?, replacingRange: NSRange, withString: String) -> String? {
guard var originalText = original else {
return nil
}
guard let range = Range<String.Index>.init(replacingRange, in: originalText) else {
return nil
}
originalText.replaceSubrange(range, with: withString)
return originalText
}
Теперь самая интересная часть, обнаружение пользовательских требований (в моем случае обнаружение возможного действительного номера мобильного телефона, где в вашем случае обнаруживается допустимая сумма)
func textFieldDidEndEditing(_ textField: UITextField) {
if textField == MY_MOBILE_TEXT_FIELD {
if nextText.IS_POSSIBLE_VALID_MOBILE_NUMBER() { // my function to detect the possible valid mobile number
textField.text = nextText
} else {
textField.text = previousText
}
}
}
Это сработало для меня, надеюсь, это сработает и для вас.
Вы можете попробовать использовать textContentType для текстового поля, чтобы iOS не испортила ваши ограничения ввода в текстовых полях.
Автозаполнение игнорирует то, что возвращают методы делегата текстового поля
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
Так что можете попробовать другой хак, который сработал для меня, Вы можете установить textContentType текстового поля суммы на тип пароля и использовать панель инструментов на клавиатуре для бокового автозаполнения предложений (поскольку вы будете использовать цифровую клавиатуру для ввода цифр в поле суммы, поэтому вы, возможно, уже используете настраиваемую панель инструментов).
amount_text_field.textContentType = .password
Таким образом, iOS будет считать, что это текстовое поле пароля, и не будет заполнять имена пользователей или пароли, которые были применены из других текстовых полей. А использование панели инструментов должно помочь вам скрыть предложения автозаполнения в этом текстовом поле.
Вы пытались явно установить в поле значение, отличное от «неопределенного»; например, имя, или, возможно, создание скрытого текстового поля с типом, установленным на имя пользователя?