多控制器管理
当app中有多个控制器的时候,我们就需要对这些控制器进行管理,为了便于控制器管理,iOS提供了两个比较特殊的控制器:UINavigationController 和 UITabBarViewController .
利用UINavigationController, 可以轻松地管理多个控制器, 轻松完成控制器之间的切换.
1> 初始化UINavigationController ;
初始化UINavigationController时, 可以通过initWithRootViewController:方法传入一个控制器作为根控制器, 这个根控制器永远处于栈底(如果栈中只有一个对象,那么根控制器也处于栈顶)
2> 设置UIWindow的rootViewController为UINavigationController ;
3> 根据具体情况,通过push方法添加对应个数的子控制器 .
UINavigationController以栈的形式保存子控制器
@property(nonatomic,copy) NSArray *viewControllers; @property(nonatomic,readonly) NSArray *childViewControllers;
使用push方法能将某个控制器压入栈
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
使用pop方法可以移除控制器
1> 将栈顶的控制器移除
-(UIViewController *)popViewControllerAnimated:(BOOL)animated;
2> 回到指定的子控制器
-(NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;
3> 回到根控制器(栈底控制器)
-(NSArray *)popToRootViewControllerAnimated:(BOOL)animated;
导航栏的内容由栈顶控制器的navigationItem属性决定
UINavigationItem有以下属性影响着导航栏的内容
1> 左上角的返回按钮
@property(nonatomic,retain) UIBarButtonItem *backBarButtonItem;
2> 中间的标题视图
@property(nonatomic,retain) UIView *titleView;
3> 中间的标题文字
@property(nonatomic,copy) NSString *title;
4> 左上角的视图
@property(nonatomic,retain) UIBarButtonItem *leftBarButtonItem;
5> 右上角的视图
@property(nonatomic,retain) UIBarButtonItem *rightBarButtonItem;
Storyboard上每一根用来界面跳转的线,都是一个UIStoryboardSegue对象,简称Segue.
每一个Segue对象,都有3个属性.
1> 唯一标识
@property (nonatomic, readonly) NSString *identifier;
2> 来源控制器
@property (nonatomic, readonly) id sourceViewController;
3> 目标控制器
@property (nonatomic, readonly) id destinationViewController;
根据Segue的执行(跳转)时刻, Segue可分为两大类型:
1> 自动型: 点击某个控件后(如按钮), 自动执行Segue ,自动完成界面跳转.
2> 手动型: 需要通过手写代码手动执行Segue, 才能完成界面跳转.
自动型Segue
如果点击某个控件后, 不需要做任何判断, 一定要跳转到下一个界面, 建议使用"自动型Segue".
手动型Segue
手动型Segue需要设置一个标识;
在恰当的时候, 使用perform方法执行对应的Segue;
[self performSegueWithIdentifier:@"login2contacts" sender:nil]; //这个self是来源控制器 Segue必须由来源控制起来执行,也就是说,这个perform方法必须由来源控制器来调用
如果点击某个控件后, 需要做一些判断,也就是说:满足一定条件后才跳转到下一个界面,建议使用"手动型Segue".
利用performSegueWithIdentifier:sender:方法可以执行某个Segue,完成界面跳转.接下来研究performSegueWithIdentifier:sender:方法的完整执行过程.
1> 根据identifier去storyboard中找到对应的线,新建UIStoryboardSegue对象.
设置Segue对象的sourceViewController(来源控制器)
创建并且设置Segue对象的destinationViewController(目标控制器)
2> 调用sourceViewController的下面方法,做一些跳转前的准备工作并且传入创建好的Segue对象.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender; // 这个sender是当初performSegueWithIdentifier:sender:中传入的sender
3> 调用Segue对象的-(void)perform;方法开始执行界面跳转操作.
(1)如果segue的style是push
1> 取得sourceViewController所在的UINavigationController;
2> 调用UINavigationController的push方法将destinationViewController压入栈中,完成跳转.
(2)如果segue的style的modal
调用sourceViewController的presenViewController方法将destinationViewController展示出来.
控制器之间的数据传递主要有两种情况:顺传和逆传.
顺传:数据的传递方向与控制器的跳转方向一致;
数据的传递方式:
在来源控制器(sourceViewController)的prepareForSegue:sender:方法中根据segue参数取得目标控制器(destinationViewController),直接给控制器传递数据(要在目标控制器(destinationViewController)的viewDidLoad方法中取得数据,来赋值给界面上的UI控件).
逆传:数据的传递方向与控制器的跳转方向相反.
数据的传递方式:
让来源控制器(sourceViewController)称为目标控制器(destinationViewController)的代理,在目标控制器(destinationViewController)中调用来源控制器(sourceViewController)的代理方法,通过代理方法的参数传递数据给来源控制器(sourceViewController).