- 什么是父子控制器
如果对于这个词熟悉的话.那个我们看一下 UIViewController,他里面有一个属性
public var childViewControllers: [UIViewController] { get }
还有一个方法
// 添加子控制器
public func addChildViewController(childController: UIViewController)
// 从父控制器中移除
public func removeFromParentViewController()
看到这写.是否大概知道下面要说的是什么了.
尤其是我们在使用一个UITabBarController.可以很明显的感觉到.
- 为什么使用父子控制器
在实际应用中, 如果只是将view添加到控制器中的话,而不是将控制器设置为父子关系话.那么有些消息传递,则无法传递到子控制器.比如说控制器的转屏,如果只是普通的添加,那么转屏的事件将无法传递给one控制器. 还有其他一些消息事件.
func click(btn: UIButton) {
let one = OneTableViewController()
one.view.frame = CGRect(x: 0, y: 64, width: self.view.frame.size.width, height: self.view.frame.size.height - 64)
self.one = one
self.view.addSubview(one.view)
}
所以我们最好是使用添加子控制器
addChildViewController(OneTableViewController())
- 什么时候使用父子控制器
如果当一个界面足够复杂,使用一个控制器进行管理的话,控制器会显得格外臃肿,这样的话,我们就有必要将View分区,然后分配到其他控制器.这样会使代码的逻辑性更强.增强可读性.简化单个控制器.
为了更方便阅读,下面贴一下控制器的代码
class ViewController: UIViewController {
// 正在显示的控制器
var showingVC: UIViewController?
override func viewDidLoad() {
super.viewDidLoad()
let view = UIView(frame: CGRect(x: 0, y: 20, width: self.view.frame.size.width, height: 44))
for i in 0..<3 {
let btn = UIButton(frame: CGRect(x: view.frame.size.width / 3.0 * CGFloat(i), y: 0, width: view.bounds.width / 3.0, height: view.bounds.height))
btn.backgroundColor = UIColor.grayColor()
btn.setTitle("btn\(i)", forState: .Normal)
btn.addTarget(self, action: "click:", forControlEvents: .TouchUpInside)
view.addSubview(btn)
}
self.view.addSubview(view)
// 通过addChildViewController,添加的控制器都会加载到childViewControllers这个数组里
addChildViewController(OneTableViewController())
addChildViewController(TwoViewController())
addChildViewController(ThreeViewController())
}
func click(btn: UIButton) {
// 先移除其他控制器的View,这样才能保证只有一个View被显示,而不是叠加在一起
showingVC?.view.removeFromSuperview()
// 获取索引
let index = btn.superview?.subviews.indexOf(btn)
// 改变当前控制器,并将view添加到主控制器
showingVC = childViewControllers[index!]
showingVC!.view.frame = CGRect(x: 0, y: 64, width: self.view.frame.size.width, height: self.view.frame.size.height - 64)
self.view.addSubview((showingVC?.view)!)
}
}
// 屏幕即将旋转时调用这个方法
extension ViewController {
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
debugPrint("\(self.classForCoder)willRotateToInterfaceOrientation")
}
}
为了说明父子控制器的重要性,我们在上面的基础上再演示一下其他的效果.
我在点击two控制器时推出一个测试控制器
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let testVC = TestViewController()
presentViewController(testVC, animated: true, completion: nil)
}
假如说,test控制器很复杂,我们添加了一个test2控制器的View.我需要的是点击test2视图的时候dismiss掉该控制器.先看看不是父子控制器会出现什么情况.
class TestViewController: UIViewController {
var test2: Test2ViewController?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.blueColor()
let test2 = Test2ViewController()
test2.view.frame = CGRect(x: 10, y: 10, width: 100, height: 100)
self.test2 = test2
view.addSubview(test2.view)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
// 为了测试是否调用了该方法
debugPrint("TestViewController")
dismissViewControllerAnimated(true, completion: nil)
}
}
同样我们在test2控制器里添加这个方法
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
debugPrint("Test2ViewController")
dismissViewControllerAnimated(true, completion: nil)
}
当我们点击test2的View时下面我将测试结果,虽然控制台打印了Test2ViewController这句话,但是控制器并没有dismiss掉,很明显,因为test2不是present出来的.
但是当我们改一下
class TestViewController: UIViewController {
// var test2: Test2ViewController?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.blueColor()
let test2 = Test2ViewController()
test2.view.frame = CGRect(x: 10, y: 10, width: 100, height: 100)
// self.test2 = test2
view.addSubview(test2.view)
addChildViewController(test2)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
debugPrint("TestViewController")
dismissViewControllerAnimated(true, completion: nil)
}
}
只是改成了父子关系,这样的话已经,点击test2区域,还是打印Test2ViewController,不同的是这是控制器被dismiss掉了.也就是说,由于父控制器是present出来的,子控制器由此得到了事件消息.这样才能确保事件在传递过程中,不会由于层级关系的问题导致消息链中断.
对于这种现象,navigation的push也同样出出现类似的问题.
网友评论