Ios 协议委托始终为零
我不熟悉使用xib文件。所以我不太清楚他们是如何与父母互动的 我有一个自定义视图(LoginView),它是从xib文件创建的。此视图还定义了一个协议(LoginDelegate)。委托的唯一目的是将用户名和密码传递回调用方 我还有一个ViewController(LoginVC),它实现了这个协议。我正在将LoginView添加到此VC 我验证了我在VC.viewDidLoad()中正确设置了委托。问题是当我尝试使用委托调用协议方法时:委托始终为nil。不知何故,它正在被清除。以下是UIView:Ios 协议委托始终为零,ios,swift,uiview,delegates,xib,Ios,Swift,Uiview,Delegates,Xib,我不熟悉使用xib文件。所以我不太清楚他们是如何与父母互动的 我有一个自定义视图(LoginView),它是从xib文件创建的。此视图还定义了一个协议(LoginDelegate)。委托的唯一目的是将用户名和密码传递回调用方 我还有一个ViewController(LoginVC),它实现了这个协议。我正在将LoginView添加到此VC 我验证了我在VC.viewDidLoad()中正确设置了委托。问题是当我尝试使用委托调用协议方法时:委托始终为nil。不知何故,它正在被清除。以下是UIVie
// 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 {...}
}
和视图控制器:
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)")
}
}
主情节提要和子xib的连接分别为:
我怀疑我在IB中没有正确连接,但我不确定。关于这个问题,我找到了很多答案。我尝试过许多提议的解决方案,但都不管用。我感谢任何意见 创建
class func getInstance() -> LoginView {
let nib = UINib(nibName:"LoginView", bundle:nil)
let view = nib.instantiate(withOwner: self, options: nil).first as! LoginView
return view
}
然后 然后从NIB中删除此函数
loadViewFromNib
执行
LoginView()时出现的当前问题
它创建一个没有布局的实例并为其设置委托,但从加载视图FromNIB
创建另一个具有正确布局的实例并将其添加到该视图中,但这会错过委托分配,因此您在vc中创建的视图的顶子视图在视图中有一个零委托从xib初始化您的LoginView
。您也没有用帧初始化它。不确定您正在点击哪个按钮,但它不在您正在viewDidLoad
中初始化的视图中。您的onLoginButtonPress
函数中还有一个额外的}。感谢您的解释-这非常有意义。我更新了我的问题以反映你的建议。我现在得到一个不同的错误。“由于未捕获的异常“NSUnknownKeyException”而终止应用程序,原因:”[setValue:forUndefinedKey:]:此类不符合密钥密码的键值编码。“我已取消所有插座和操作的布线/重新布线,但我收到相同的错误。”。我仍然怀疑接线有问题。LoginView代理应该连接到文件所有者还是LoginVC?我添加了一个连接的屏幕截图。
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)