协议委托在自定义 UIView 按钮中不起作用 [英] Protocol delegate not working within custom UIView button

查看:28
本文介绍了协议委托在自定义 UIView 按钮中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have been trying to create a protocol and delegate within my custom UIView subclass, but when I call it on View Controller class the button is not responding to the method. I have read almost all the answers on StackOverflow, none of them solve my issue. Here is the procedure I have followed:

创建 require 委托:

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)

在类内调用委托:

View Controller Class (View B)

Call the delegate within the class:

class AccessViewController: UIViewController, LoginDelegates

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

In here I tried multiple approaches I have found on SO and around web. but none of them seems to work for me, the button still doesn't respond.

方法 1:

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

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

Approach 2: with this approach, I get the following error doesn't contain a view controller with identifier 'LoginViewController', which make sense cause the view is subclass and not within the storyboard.

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

}

当然,调用当前视图中的方法.

and of course, call the method in the current view.

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

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

I also try to create a swift file and just put all the protocols separate from both views and just call them when needed. and At this point, I have no other option. Thank you for help in advance.

推荐答案

像这样更新你的 LoginViewController:

Update your LoginViewController like so:

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:

Update your AccessViewController like so:

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 活动实例的引用.

The problem you have caused because you don't have access to your active instance of LoginViewController. In both your approaches you create a new instance of LoginViewController but you need to access existing instance. To make this you have to create static variable which will keeps for you a reference to the active instance of the LoginViewController.

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

Also please remember that in most cases you have to mark delegate variable as weak to avoid memory leaks.

因为您直接在 AccessViewController 视图中加载和呈现 LoginViewController 的视图,所以您的 LoginViewController 不是 firstResponder.因此,按下按钮时不会调用按钮的操作.

Because of you load and present view of your LoginViewController directly in AccessViewController view your LoginViewController is not the firstResponder. Because of this the action of your button is not called while pressing.

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

You can make some trick in your AccessViewController class

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)
   }
}

这篇关于协议委托在自定义 UIView 按钮中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆