Mer*_*ury 2 parent-child superview swift swift3
我在UIViewController中实例化了一个子UIView类,UIViewController有一个名为sigIn(){}的函数.我需要在UIView中调用这个函数.
我尝试使用self.superview并将其转换为UIViewController,但这不起作用.我发现了一种使用侦听器来检测触发器的方法,但我认为这不是一个好的解决方案.在子视图的paren视图中是否有另一种简单的方法来访问函数?
class SignUIView: UIView {
func signInUIButtonH(sender: UIButton) {
("Call parent signIn() function")
}
(init etc. ...)
}
Run Code Online (Sandbox Code Playgroud)
首先,View和View Controller是两个不同的概念..superview不会给你一个视图控制器,并且它只会使程序崩溃.
虽然可以找到当前的View Controller,但它在您的使用案例中非常简单,因为您无法确定View Controller是否具有该signIn()功能,您甚至无法确保"当前View Controller"是View Controller的视图控制器.风景.
iOS通常使用"委托模式".在你的情况,必须首先定义一个协议的signIn()功能:
protocol SignInDelegate {
func signIn()
}
Run Code Online (Sandbox Code Playgroud)
然后,View需要提供此协议的变量.此变量称为委托.每当我们想要登录时,只需调用委托的signIn()功能即可.
变量应该是弱参考,以避免强引用周期.协议也需要是类绑定的,否则编译器会抱怨.
protocol SignInDelegate: class { // <-- needs :class for weak
func signIn()
}
class SignUIView: UIView {
weak var delegate: SignInDelegate? // <-- delegate
func signInUIButtonH(sender: UIButton) {
delegate?.signIn() // <-- call the delegate
}
}
Run Code Online (Sandbox Code Playgroud)
接下来,我们将协议调整为View Controller:
class SignInViewController: UIViewController, SignInDelegate { // <-- adapt the protocol
func signIn() { // <-- implement the function
print("sign in")
}
override func viewDidLoad() {
super.viewDidLoad()
signInView.delegate = self // <-- tell the subview we will be the delegate.
}
}
Run Code Online (Sandbox Code Playgroud)
我们通常会将此委托公开给Interface Builder,因此我们只需将View连接到View Controller即可分配委托.
这是通过添加@IBOutlet到委托字段来完成的.不幸的是,Xcode只识别AnyObject/ NSObject用于IBOutlet,这违背了使用委托模式进行类型安全的整个目的.所以我们需要引入一些丑陋的黑客来为IB解决它.该协议现在也需要,@objc因为解析这些IB连接需要Objective-C运行时.
@objc protocol SignInDelegate { // <-- needs @objc for IB (:class is implied by @objc)
func signIn()
}
class SignUIView {
// Blame Xcode for this mess. See https://stackoverflow.com/a/42227800/224671
#if TARGET_INTERFACE_BUILDER
@IBOutlet weak var delegate: AnyObject?
#else
weak var delegate: SignInDelegate?
#endif
func signInUIButtonH(sender: UIButton) {
delegate?.signIn()
}
}
class SignInViewController: UIViewController, SignInDelegate { // <-- adapt the protocol
func signIn() { // <-- implement the function
print("sign in")
}
// Note: no need to set signInView.delegate manually.
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6055 次 |
| 最近记录: |