Swift3 在子视图中的父函数外调用函数
Swift3 Call function in parent out of function in child view
我有一个在 UIViewController 中实例化的子 UIView class,UIViewController 有一个名为 sigIn(){} 的函数。我需要从 UIView 中调用这个函数。
我尝试以某种方式使用 self.superview 并将其转换为 UIViewController 但这没有用。我找到了一种使用侦听器检测触发器的方法,但我认为这不是一个好的解决方案。是否有另一种简单的方法可以从子视图访问父视图中的函数?
class SignUIView: UIView {
func signInUIButtonH(sender: UIButton) {
("Call parent signIn() function")
}
(init etc. ...)
}
为 signIn()
函数声明一个协议,并让父 [=15=] 遵守该协议。然后让父 ViewController 成为 SignUIView
的委托:
protocol SignInProtocol {
func signIn()
}
class MyViewController: UIViewController, SignInProtocol {
var signUIView: SignUIView
override func viewDidLoad() {
super.viewDidLoad()
self.signUIView = SignUIView()
self.signUIView.delegate = self // set the delegate
}
func signIn() {
...
}
}
class SignUIView: UIView {
var delegate: SignProtocol? // the delegate
func signInUIButtonH(sender: UIButton) {
// call the delegate
self.delegate?.signIn()
}
(init etc. ...)
}
首先,。 .superview
不会给你一个 View Controller,转换它只会使程序崩溃。
虽然 it is possible to find out the current View Controller,但它在您的用例中非常不合常理,因为您无法确定 View Controller 是否具有 signIn()
功能,您甚至无法确保 "current View Controller"是视图的视图控制器。
iOS 通常使用 代替。在您的情况下,首先为 signIn()
函数定义一个 协议 :
protocol SignInDelegate {
func signIn()
}
那么View需要提供一个这个协议的变量。此变量称为 delegate。每当我们想登录时,只需调用委托的 signIn()
函数即可。
变量应该是对. The protocol also 的弱引用,否则编译器会报错。
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
}
}
接下来我们调整协议以适应视图控制器:
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.
}
}
我们通常将此委托公开给 Interface Builder,因此我们可以简单地将视图连接到视图控制器以分配委托。
这是由 adding @IBOutlet
to the delegate field. Unfortunately, Xcode only recognizes AnyObject
/NSObject
for IBOutlet 完成的,这违背了使用委托模式实现类型安全的全部目的。所以我们需要引入一些丑陋的 hack 来为 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
#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.
}
我有一个在 UIViewController 中实例化的子 UIView class,UIViewController 有一个名为 sigIn(){} 的函数。我需要从 UIView 中调用这个函数。
我尝试以某种方式使用 self.superview 并将其转换为 UIViewController 但这没有用。我找到了一种使用侦听器检测触发器的方法,但我认为这不是一个好的解决方案。是否有另一种简单的方法可以从子视图访问父视图中的函数?
class SignUIView: UIView {
func signInUIButtonH(sender: UIButton) {
("Call parent signIn() function")
}
(init etc. ...)
}
为 signIn()
函数声明一个协议,并让父 [=15=] 遵守该协议。然后让父 ViewController 成为 SignUIView
的委托:
protocol SignInProtocol {
func signIn()
}
class MyViewController: UIViewController, SignInProtocol {
var signUIView: SignUIView
override func viewDidLoad() {
super.viewDidLoad()
self.signUIView = SignUIView()
self.signUIView.delegate = self // set the delegate
}
func signIn() {
...
}
}
class SignUIView: UIView {
var delegate: SignProtocol? // the delegate
func signInUIButtonH(sender: UIButton) {
// call the delegate
self.delegate?.signIn()
}
(init etc. ...)
}
首先,.superview
不会给你一个 View Controller,转换它只会使程序崩溃。
虽然 it is possible to find out the current View Controller,但它在您的用例中非常不合常理,因为您无法确定 View Controller 是否具有 signIn()
功能,您甚至无法确保 "current View Controller"是视图的视图控制器。
iOS 通常使用 signIn()
函数定义一个 协议 :
protocol SignInDelegate {
func signIn()
}
那么View需要提供一个这个协议的变量。此变量称为 delegate。每当我们想登录时,只需调用委托的 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
}
}
接下来我们调整协议以适应视图控制器:
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.
}
}
我们通常将此委托公开给 Interface Builder,因此我们可以简单地将视图连接到视图控制器以分配委托。
这是由 adding @IBOutlet
to the delegate field. Unfortunately, Xcode only recognizes AnyObject
/NSObject
for IBOutlet 完成的,这违背了使用委托模式实现类型安全的全部目的。所以我们需要引入一些丑陋的 hack 来为 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
#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.
}