我有ViewController
调用自定义类PopOverModal
并传入自己和子ViewController。
class ViewController: UIViewController {
...
@IBAction func testPopOver(_ sender: Any) {
var childVC = // initialize child view controller with view from storyboard
var myPopOverModal = PopOverModal(parent: self, child: childVC);
}
...
}
我需要childVC将一些任务委托给PopOverModal。
class ChildViewController: UIViewController {
...
weak var delegate: PopOverModal?
...
}
class PopOverModal {
init(parent: UIViewController, child: UIViewController) {
child.delegate = self
child.dismiss(animated: true, completion: nil)
}
}
PopOverModal的初始化程序会出错,因为UIViewController没有属性delegate
。
然后我做了以下事情:
protocol PopOverViewController: class {
weak var delegate: PopOverModal? {get set}
}
class ChildViewController: UIViewController, PopOverViewController {
...
weak var delegate: PopOverModal?
...
}
class PopOverModal {
init(parent: UIViewController, child: PopOverViewController) {
child.delegate = self
child.dismiss(animated: true, completion: nil)
}
}
但是,现在我收到dismiss
不是PopOverViewController函数的错误。
如果确保ChildViewController继承自UIViewController,我能做些什么才能访问UIViewController和PopOverViewController的函数和属性?
我知道我可以创建一个继承自UIViewController并符合PopOverViewController的Hybrid类,让我的ChildViewController继承它,但还有另一种方法吗?
答案 0 :(得分:1)
如果保证child
将是ChildViewController
类的实例,那么您可以修改初始化程序签名,以便它接受相应的对象:
init(parent: UIViewController, child: ChildViewController) {
child.delegate = self
child.dismiss(animated: true, completion: nil)
}
如果它可以是任意UIViewController,但delegate
仅适用于ChildViewController
的实例,那么您可以使用带有可选链接或可选绑定的类型转换:
// Option #1 - optional chaining
init(parent: UIViewController, child: UIViewController) {
(child as? ChildViewController)?.delegate = self
child.dismiss(animated: true, completion: nil)
}
// Option #2 - optional binding
init(parent: UIViewController, child: UIViewController) {
if let child = child as? ChildViewController {
child.delegate = self
}
child.dismiss(animated: true, completion: nil)
}
顺便说一下,使用基于协议的委派被认为是最佳实践。以下是如何完成的示例:
protocol PopOverDelegate: class {
// add any methods and properties that the delegate should implement
func didPressButton()
}
class ChildViewController: UIViewController {
...
weak var delegate: PopOverDelegate?
...
// call delegate methods where you need them
func onButtonPress() {
self.delegate?.didPressButton()
}
}
class PopOverModal: PopOverDelegate {
init(parent: UIViewController, child: UIViewController) {
(child as? ChildViewController)?.delegate = self
child.dismiss(animated: true, completion: nil)
}
// MARK: - delegate methods
func didPressButton() {
print(#function)
}
}