Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何检测用户何时在UITextField上使用密码自动填充_Ios_Uitextfield_Autofill_Uitextfielddelegate - Fatal编程技术网

Ios 如何检测用户何时在UITextField上使用密码自动填充

Ios 如何检测用户何时在UITextField上使用密码自动填充,ios,uitextfield,autofill,uitextfielddelegate,Ios,Uitextfield,Autofill,Uitextfielddelegate,我已经实现了在iOS 11上支持密码自动填充所需的所有应用程序和服务器更改,并且运行良好。我希望它能工作得更好一点 我的用户名和密码字段是UITextFields。我想确定用户何时“自动填充”了两个UITextField中的一个,以便我可以进入下一步。当前,用户自动填充一个项目,然后需要按屏幕键盘上的“下一步”按钮才能前进。我想代表用户触发这个 WWDC2017密码自动填充会话要求使用UITextFieldTextDidChange。这是可行的,但当用户手动键入这些字段时,当然也会触发 我的想法

我已经实现了在iOS 11上支持密码自动填充所需的所有应用程序和服务器更改,并且运行良好。我希望它能工作得更好一点

我的用户名和密码字段是UITextFields。我想确定用户何时“自动填充”了两个UITextField中的一个,以便我可以进入下一步。当前,用户自动填充一个项目,然后需要按屏幕键盘上的“下一步”按钮才能前进。我想代表用户触发这个

WWDC2017密码自动填充会话要求使用UITextFieldTextDidChange。这是可行的,但当用户手动键入这些字段时,当然也会触发

我的想法是将先前版本的文本与新版本的文本进行比较,并假设如果长度从零增加到大于某个最小长度(2或更多),则用户使用自动填充。这在大多数情况下都会起作用,但有错误触发的风险(可能是在慢速设备上快速键入)。所以对我来说,这可能是一个冒险的假设


我很好奇是否有人找到了一种更可靠的方法来确定UITextField上是否使用了密码自动填充,或者只是认为我对错误触发器的担心是没有根据的。

我认为没有更好的解决方案

我注意到的一点是,只有当文本字段为空时,才会启用自动填充

因此,如果文本字段从空变为大于最小密码/用户名的长度,则很可能是自动填充/粘贴

我正在使用中的
shouldChangeCharacters检测UITextField中的更改。我不确定是否存在这样的情况,即在调用委托方法之前可以将键盘上的文本批处理在一起。

找到了解决方案

当密码管理器用于自动填写用户名+密码时,它将触发
didBeginEditing
两次,速度比人类更快

所以,我计算两个事件之间的时间。如果时间非常快,那么我假设autofill(例如FaceID或TouchID)用于输入凭据并自动触发下一个UI——在我的情况下,用户点击“登录”

显然,您必须为要监视的UITextFields设置正确的委托,但一旦设置了,则:

var biometricAutofillTime: Date!

func textFieldDidBeginEditing(_ textField: UITextField) {
    if biometricAutofillTime != nil {
        if Date().timeIntervalSince(biometricAutofillTime) < 0.1 {
            // NOTE: Need to hesitate for a very short amount of time,
            //        because, otherwise, the second UITextField (password)
            //        won't yet be populated
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { self.didTapSignin() }
        }
        biometricAutofillTime = nil
    }
    biometricAutofillTime = Date()
}
var自动填充时间:日期!
func textField didbeginediting(textField:UITextField){
如果自动填充时间!=零{
如果日期()时间间隔(自动填充时间)<0.1{
//注意:需要在很短的时间内犹豫,
//因为,否则,第二个UITextField(密码)
//还不会被填充
DispatchQueue.main.asyncAfter(截止日期:.now()+0.2){self.didTapSignin()}
}
自动填充时间=零
}
自动填充时间=日期()
}

不确定前面的答案是否在某个时候停止工作,但我无法让它工作-当使用自动填充时,我只收到一个
didbegineediting
调用

然而,我确实找到了一种检测自动填充的方法。请记住,在输入了一些字符后,可以使用自动填充,例如,如果用户已经在电话号码中键入了一些号码,则他们会自动填充完整的号码

对于Swift 4/5:

private var fieldPossibleAutofillReplacementAt:Date?
私有变量fieldPossibleAutofillReplacementRange:NSRange?
func textField(textField:UITextField,shouldChangeCharacters范围:NSRange,replacementString:string)->Bool{
//要检测自动填充,请查找两个快速替换。第一个替换用单个空格替换范围
//(或以iOS 13.4开头的空白字符串)。
//下一个将用自动填充的内容替换相同的范围。
如果字符串=“”| |字符串=“”{
self.fieldPossibleAutofillReplacementRange=范围
self.fieldPossibleAutofillReplacementAt=Date()
}否则{
如果fieldPossibleAutofillReplacementRange==range,则让replacedAt=self.fieldPossibleAutofillReplacementAt,Date()。时间间隔(replacedAt)<0.1{
DispatchQueue.main.async{
//无论你用什么来前进。
self.moveForward()
}
}
self.fieldPossibleAutofillReplacementRange=nil
self.fieldPossibleAutofillReplacementAt=nil
}
返回真值
}
我想代表用户触发这个

如果这是你的主要目标,我在这里做一点不同的方法

在显示登录表单时,我首先使用
SecRequestSharedWebCredential
检查iCloud密钥链。如果闭包返回凭证,这意味着用户的意图是使用凭证登录,那么我会自动为他/她登录。否则,请将登录文本字段设置为becomeFirstResponder()


这种方法不支持第三方密码管理器,但我相信大多数人都使用iCloud钥匙链。

我找到了另一种简单的方法。。希望它能帮助寻找它的人

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Usually string is coming as single character when user hit the keyboard .. 
// but at AutoFill case it will come as whole string which recieved .. 
// at this moment you can replace what you currently have by what you have recieved.
// In below case I'm expecting to recieve 4 digits as OTP code .. you can change it by what you are expecting to recieve.
    if string.count == 4 {
            doWhatEverYouByAutoFillString(text: string)
            return true
        } 
    }
}

这会检测用户何时通过密码自动填充。当用户从剪贴板粘贴文本时,也可能触发此错误。(如果textfield为空)

您可能可以通过此链接处理删除用户粘贴案例的逻辑。。


Swift 5:

每次用户在textfield中键入内容时,都会触发以下委托方法。该字符串计数通常为一,因此任何大于该值的数字都是自动填充或用户将一些文本粘贴到字段中。我仅在此密码字段上使用此委托

extension LoginView: UITextFieldDelegate {

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if string.count > 1 {
            DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) { [weak self] in
                self?.endEditing(true)
            }
        }
        return true
    }
}

我还想通过在应用程序的分析中添加使用情况来了解用户是否真的使用了密码自动填充。我们对1Password也这样做。这仍然是不可解的吗?这不再是真的了。“自动完成”确实需要一个空白字段,它将替换任何现有文本。我正在接收
extension LoginView: UITextFieldDelegate {

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if string.count > 1 {
            DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) { [weak self] in
                self?.endEditing(true)
            }
        }
        return true
    }
}