简体   繁体   中英

Protocol delegate is always nil

I am new to using xib files. So I'm not very clear on how they interact with their parent.

I have a custom view (LoginView) which is created from a xib file. This view also defines a protocol (LoginDelegate). The sole purpose of the delegate is to pass the username and password back to the caller.

I also have a ViewController (LoginVC) which implements this protocol. I am adding the LoginView to this VC.

I verified that I properly set the delegate in VC.viewDidLoad(). The problem is when I try to use the delegate to invoke the protocol method: the delegate is always nil. Somehow it is getting cleared. Here is the UIView:

// MARK:- Login Delegate method
// provide a means to pass the user credentials back to the parent
protocol LoginDelegate: AnyObject {
    func getUsernameAndPassword(user: String, pwd: String)
}

class LoginView: UIView, UITextViewDelegate {

    @IBOutlet weak var user: UITextView!
    @IBOutlet weak var password: UITextView!
    @IBOutlet weak var btnLogin: UIButton!
    var userPlaceholderLabel : UILabel!
    var pwdPlaceholderLabel : UILabel!
    var view: UIView!

    weak var loginDelegate: LoginDelegate?


    // MARK:- internal use only
    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    class func getInstance() -> LoginView {
      let nib = UINib(nibName:"LoginView", bundle:nil)
      let view = nib.instantiate(withOwner: self, options: nil).first as! LoginView
      return view
    }

    @IBAction func onLoginButtonPress(_ sender: Any) {
        print ("\(#function): Username: \(user.text ?? ""), Password: \(password.text ?? "")")

        self.loginDelegate?.getUsernameAndPassword(user: user.text, pwd: password.text )
    }

    // MARK:- TextView Delegate methods
    func textViewDidChange(_ textView: UITextView) {...}  
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {...}
}

And the View Controller:

class LoginVC: UIViewController, LoginDelegate {

    var isBleScan = true
    @IBOutlet weak var btnToggleBleScan: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        let loginSubview = LoginView.getInstance()
        loginSubview.frame = self.view.bounds
        loginSubview.loginDelegate = self
        view.addSubview(loginSubview)
    }

    @IBAction func onToggleScanPressed(_ sender: Any) {
        isBleScan = !isBleScan
        if (isBleScan) {
            btnToggleBleScan.setTitle("Stop Scan", for: UIControl.State.normal)
        } else {
            btnToggleBleScan.setTitle("Start Scan", for: UIControl.State.normal)
        }
    }

    // MARK:- LoginDelegate methods
// METHOD IS NEVER CALLED - DELEGATE IS nil IN THE CALLER
    func getUsernameAndPassword(user: String, pwd: String) {
        let _user = user
        let _pwd = pwd
        print ("\(#function):Username: \(_user), Password: \(_pwd)")        
    }
}

The Connections for the Main Storyboard and Child xib, respectively: 主故事板 LoginVC(又名主)

登录查看xib LoginView(又名孩子) I suspect I am not wiring things properly in IB, but I'm unsure. I have found many answers regarding this problem. I have tried many proposed solutions, but nothing works. I appreciate any input!

Create

  class func getInstance() -> LoginView { 
    let nib = UINib(nibName:"LoginView", bundle:nil)
    let view = nib.instantiate(withOwner: self, options: nil).first as! LoginView
    return view
  }

then

    let loginSubview = LoginView.getInstance()
    loginSubview.frame = self.view.bounds
    loginSubview.loginDelegate = self   // I verified this sets the delegate to an instance of LoginVC
    view.addSubview(loginSubview)

Then remove this function loadViewFromNib


current problem when you do LoginView() it creates an instance without it's layout and set the delegate for it but from your loadViewFromNib you create another instance with correct layout and add it to that view but this misses delegate assignment hence the top subview of the view you create in the vc has a nil delegate

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM