协议委托不在自定义UIView按钮

时间:2018-04-14 18:14:17

标签: ios swift xcode swift4

我一直在尝试在我的自定义UIView子类中创建协议和委托,但是当我在View Controller类上调用它时,按钮没有响应该方法。我已经阅读了StackOverflow上的几乎所有答案,但没有一个能解决我的问题。这是我遵循的程序:

UIView子类(查看A)

创建需要委托:

protocol LoginDelegates {
    func loginButtonPressed(sender: AnyObject)
}

在子类

class LoginViewController: UIViewController {

    @IBOutlet weak var loginButton: UIButton!

    var delegate: LoginDelegates? // Initite the delegate variable

    //Login Button Action
    @IBAction func loginButtonPressed(_ sender: UIButton) {
       delegate?.loginButtonPressed(sender: loginButton)
    }
}

查看控制器类(视图B)

在班级内呼叫代表:

class AccessViewController: UIViewController, LoginDelegates

在这里,我尝试了在SO和网络上找到的多种方法。但是它们似乎都不适合我,按钮仍然没有响应。

方法1:

override func viewDidLoad() {
    super.viewDidLoad()
    //Assign the delegate in current view
    let LoginView = LoginViewController()
    LoginView.delegate = self
}

Approach 2 使用这种方法,我得到以下错误doesn't contain a view controller with identifier 'LoginViewController',这是有道理的,因为视图是子类而不是故事板。

override func viewDidLoad() {
    super.viewDidLoad()
    //Assign the delegate in current view
    if let loginView = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as? LoginViewController {
        loginView.delegate = self
    }

}

当然,请在当前视图中调用该方法。

func loginButtonPressed(sender: AnyObject) {
     performSegue(withIdentifier: "toDashboard", sender: self)
}

我还尝试创建一个swift文件,只是将所有协议与两个视图分开,并在需要时调用它们。而在这一点上,我别无选择。提前谢谢你的帮助。

1 个答案:

答案 0 :(得分:2)

像这样更新你的LoginViewController:

class LoginViewController: UIViewController {

    static weak var shared: LoginViewController?

    @IBOutlet weak var loginButton: UIButton!

    weak var delegate: LoginDelegates? // Initite the delegate variable

    //Login Button Action
    @IBAction func loginButtonPressed(_ sender: UIButton) {
       delegate?.loginButtonPressed(sender: loginButton)
    }

    override func viewDidLoad() {
       super.viewDidLoad()
       // All your viewDidLoad stuff

       LoginViewController.shared = self

    }
}

像这样更新你的AccessViewController:

class AccessViewController: UIViewController, LoginDelegates {


   override func viewDidLoad() {
      super.viewDidLoad()
      // All your viewDidLoad stuff

      LoginViewController.shared?.delegate = self

   }

   func loginButtonPressed(sender: AnyObject) {
      performSegue(withIdentifier: "toDashboard", sender: self)
   }
}

由于您无法访问LoginViewController的活动实例而导致的问题。在这两种方法中,您都创建了一个新的LoginViewController实例,但您需要访问现有实例。为此,您必须创建静态变量,它将为您提供对LoginViewController的活动实例的引用。

另请注意,在大多数情况下,您必须将委托变量标记为弱以避免内存泄漏。

由于您在AccessViewController视图中直接加载并显示LoginViewController的视图,因此您的LoginViewController不是第一个响应者。因此,按下时不会调用按钮的操作。

您可以在AccessViewController类中制作一些技巧

class AccessViewController: UIViewController, LoginDelegates {


   override func viewDidLoad() {
      super.viewDidLoad()
      // All your viewDidLoad stuff

      let loginVC = LoginViewController()

      loginVC.loginButton.addTarget(self, action: #selector(self.loginButtonPressed), for: .touchUpInside)

      //add your LoginViewController view as subview to your AccessController view.

   }

   @objc func loginButtonPressed() {
      performSegue(withIdentifier: "toDashboard", sender: self)
   }
}