首页 > 解决方案 > 用于实例化 ViewController 的按钮在隐藏后不起作用

问题描述

我有一个非常奇怪的问题,我刚刚发现......

我有这个button触发这个function

@objc func vergessenTapped() {
    let forgotPasswordVC = self.storyboard?.instantiateViewController(withIdentifier: "ForgotPasswordVC") as! ForgotPasswordVC
    forgotPasswordVC.email = self.emailTextField.text!
    self.present(forgotPasswordVC, animated: true, completion: nil)
}

我也有这些hide/上面show的功能button

    // delegate Methode für eye-Button
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
    switch textField {
    case passwordTextField:
        if passwordTextField.text != "" {
            eyeButton.isHidden = false
            vergessenButton.isHidden = true
        } else {
            eyeButton.isHidden = true
        }

        break
    default:
        break
    }
    return true
}
// delegate Methode für eye-Button
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
    
    if textField == passwordTextField {
        self.eyeButton.isHidden = true
        self.vergessenButton.isHidden = false
    }
    return true
}

@objc func textFieldDidChange(_ textField: UITextField) {
    if textField.text == "" {
        self.eyeButton.isHidden = true
        self.vergessenButton.isHidden = false
    }else {
        self.vergessenButton.isHidden = true
        self.eyeButton.isHidden = false
    }
}

现在的问题:

当我在上述任何内容隐藏它button之前第一次按下时,它工作得很好。delegate-functionViewControllerpresents

但是:一旦按钮第一次被隐藏,并且用户在它再次可见后单击它,forgotpasswordViewController行为真的很奇怪,例如:

1.调用时self.dismiss,`ViewController 实际上并没有被关闭,而是弹出它下面的 那个。

@objc func backButtonTapped(){
    self.dismiss(animated: true, completion: nil)
}

2.button中的(forgotpasswordViewController 只有一个按钮)没有做任何事情。

这是一个屏幕视频,以便更好地理解。进入视频 22 秒后,我开始输入(不知何故在屏幕视频上不可见,但您可以看到“vergessen”但消失并再次出现。再次出现后,我单击它,如您所见,既不像他们所做的那样,也不像他们所做backButton的那样工作confirmButton前...

这是某种错误吗???我无法解释..所以如果有人在这里帮助我,我将不胜感激!

演示项目:

演示项目

标签: iosswiftuiviewcontrolleruibutton

解决方案


它与显示和隐藏 Vergessen 按钮无关。问题是您的 ForgotPassword 视图控制器(实际上也是您的其他视图控制器)中的这种事情:

let backButton: UIButton = {
    let v = UIButton()
    v.translatesAutoresizingMaskIntoConstraints = false
    v.setImage(UIImage(named:"down"), for: .normal)
    v.addTarget(self, action: #selector(backButtonTapped), for: .touchUpInside)
    return v
}()

这是非常错误的。你明白它是什么吗?当然不是,因为这是所有 iOS 编程中最糟糕的小陷阱之一。您不能v.addTarget(self...在实例属性的初始化程序中说。为什么?因为实例self(这里是视图控制器)是我们正在初始化的对象。所以self这里没有任何意义。嗯,有时它有意义,有时没有;对你来说真正的陷阱是代码曾经工作过。这真的误导了你。(你也被代码编译的事实误导了。在我看来,它不应该。我已经提交了一个错误,如果它有任何安慰的话。)

好的,所以我可以想到很多解决方案,但传统上我们在这里所做的是替换letlazy var. 我想我在你的代码中有六个地方需要这样做。

lazy var backButton: UIButton = { // ... and so on

当你这样做时,一切都会开始正常工作。

解决问题的原因是lazy推迟了代码的运行,直到视图控制器本身被初始化之后。所以 thenself意味着它应该是什么意思。

(很抱歉,没有lazy let,但我对此无能为力。你只需要说lazy var出来就可以了。)

我还应该补充一点,iOS 14 中的新功能,您可以(如果您愿意) stop call addTarget(_:action:for:),这样您就不会再掉入这个陷阱了。但修复,即向按钮添加 UIAction,仅适用于 iOS 14 及更高版本。


推荐阅读