iOS5中 UIViewController新方法的使用

前言

在苹果的WWDC2011大会视频的 《Session 101 - What’s New in Cocoa》 和 《Session 102 - Implementing UIViewController Containment》 中介绍了苹果在iOS5中给UIViewController新增加的5方法以及一个属性:

1
2
3
4
5
6
7
8
// 方法
addChildViewController:
removeFromParentViewController:
transitionFromViewController:toViewController:duration:options:animations:completion:
willMoveToParentViewController:
didMoveToParentViewController:
// 属性
@property(nonatomic,readonly) NSArray *childViewControllers

原来的问题

这些新增的方法和属性用于改进我们的编程方式。那么让我们先看看以前的对于UIViewController的使用有什么潜在的问题,认清问题,我们才能理解苹果改变的意义。

在以前,一个UIViewController的View可能有很多小的子view。这些子view很多时候被盖在最后,我们在最外层ViewController的viewDidLoad方法中,用addSubview增加了大量的子view。这些子view大多数不会一直处于界面上,只是在某些情况下才会出现,例如登陆失败的提示view,上传附件成功的提示view,网络失败的提示view等。但是虽然这些view很少出现,但是我们却常常一直把它们放在内存中。另外,当收到内存警告时,我们只能自己手工把这些view从super view中去掉。

改变

苹果新的API增加了addChildViewController方法,并且希望我们在使用addSubview时,同时调用[self addChildViewController:child]方法将sub view对应的viewController也加到当前ViewController的管理中。对于那些当前暂时不需要显示的subview,只通过addChildViewController把subViewController加进去。需要显示时再调用transitionFromViewController:toViewController:duration:options:animations:completion方法。

另外,当收到系统的Memory Warning的时候,系统也会自动把当前没有显示的subview unload掉,以节省内存。

参考资料

关于这个,这儿有一篇不错的文章介绍了一段sample代码用于演示新API的使用.

我也将其代码稍加修改,增加了view load, unload, appear, disappear的事件Log,以及收到Memory Warning时的Log。代码放在了github上,地址是这里,感兴趣的同学可以自己下载下来看看源码。

可以看到,这些view在没有使用时,是不会被load的,并且当有Memory Warning时,当前没有显示的view自动被unload掉了。所以新的方法确实能有效地节省内存,也能方便地处理内存不足时的资源回收。运行Log如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[7397:f803] -[FirstViewController willMoveToParentViewController:]
[7397:f803] -[SecondViewController willMoveToParentViewController:]
[7397:f803] -[ThirdViewController willMoveToParentViewController:]
[7397:f803] -[ThirdViewController viewDidLoad]
[7397:f803] -[ThirdViewController viewWillAppear:]
[7397:f803] -[ThirdViewController viewDidAppear:]
[7397:f803] 生日提醒
[7397:f803] -[SecondViewController viewDidLoad]
[7397:f803] -[ThirdViewController viewWillDisappear:]
[7397:f803] -[SecondViewController viewWillAppear:]
[7397:f803] -[SecondViewController viewDidAppear:]
[7397:f803] -[ThirdViewController viewDidDisappear:]
[7397:f803] 留言及回复
[7397:f803] -[FirstViewController viewDidLoad]
[7397:f803] -[SecondViewController viewWillDisappear:]
[7397:f803] -[FirstViewController viewWillAppear:]
[7397:f803] -[FirstViewController viewDidAppear:]
[7397:f803] -[SecondViewController viewDidDisappear:]
[7397:f803] Received memory warning.
[7397:f803] -[SecondViewController viewDidUnload]
[7397:f803] -[ThirdViewController viewDidUnload]

 Feb 6th, 2012  iOS

原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0

另一篇相关的详细例子:

addChildViewController: 
removeFromParentViewController 
transitionFromViewController:toViewController:duration:options:animations:completion:
willMoveToParentViewController: 
didMoveToParentViewController:

下面详细介绍一下addChildViewController,一个ViewController可以添加多个子ViewController,但是这些子ViewController只有一个是显示到父视图中的,可以通过transitionFromViewController:toViewController:duration:options:animations:completion:这个方法转换显示的子视图。同时加入相应的动画。下面以一个例子来说明,最后实现的效果:

 

下面详细介绍一下上述效果的实现:

创建项目,changeViewController。
添加相应的viewController,MainViewController、FirstViewController、SecondViewController、ThirdViewController。如下图:


3.把MainViewController添加到window中。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
// Override point for customization after application launch. 
MainViewController *mainViewController=[[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil]; 
self.window.rootViewController=mainViewController; 
[self.window makeKeyAndVisible]; 
return YES; 
}

4.在MainViewController中添加三个按钮,并且连接onClickbutton方法。

5.在MainViewController中添加三个子controller

#pragma mark – View lifecycle

- (void)viewDidLoad 

[super viewDidLoad]; 
// Do any additional setup after loading the view from its nib. 

FirstViewController *firstViewController=[[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil]; 
[self addChildViewController:firstViewController]; 

SecondViewController *secondViewController=[[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil]; 
[self addChildViewController:secondViewController]; 


ThirdViewController *thirdViewController=[[ThirdViewController alloc] initWithNibName:@"ThirdViewController" bundle:nil]; 
[self addChildViewController:thirdViewController]; 

[contentView addSubview:thirdViewController.view]; 

currentViewController=thirdViewController; 

}

其中要把其中的一个子controller的view添加到根视图中,这样才能显示出相应的视图。

6.点击按钮,切换视图。

-(IBAction)onClickbutton:(id)sender 

FirstViewController *firstViewController=[self.childViewControllers objectAtIndex:0]; 
ThirdViewController *thirdViewController=[self.childViewControllers objectAtIndex:2]; 
SecondViewController *secondViewController=[self.childViewControllers objectAtIndex:1]; 
if ((currentViewController==firstViewController&&[sender tag]==1)||(currentViewController==secondViewController&&[sender tag]==2) ||(currentViewController==thirdViewController&&[sender tag]==3) ) { 
return; 

UIViewController *oldViewController=currentViewController; 
switch ([sender tag]) { 
case 1: 

NSLog(@"留言及回复"); 
[self transitionFromViewController:currentViewController toViewController:firstViewController duration:4 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{ 
} completion:^(BOOL finished) { 
if (finished) { 
currentViewController=firstViewController; 
}else{ 
currentViewController=oldViewController; 

}]; 

break; 
case 2: 

NSLog(@"生日提醒"); 
[self transitionFromViewController:currentViewController toViewController:secondViewController duration:1 options:UIViewAnimationOptionTransitionFlipFromTop animations:^{ 

} completion:^(BOOL finished) { 
if (finished) { 
currentViewController=secondViewController; 
}else{ 
currentViewController=oldViewController; 

}]; 

break; 
case 3: 

NSLog(@"好友申请"); 
[self transitionFromViewController:currentViewController toViewController:thirdViewController duration:1 options:UIViewAnimationOptionTransitionFlipFromBottom animations:^{ 

} completion:^(BOOL finished) { 
if (finished) { 
currentViewController=thirdViewController; 
}else{ 
currentViewController=oldViewController; 

}]; 

break; 
default: 
break; 

}

其中我把按钮设置成不同的tag了。

这时候点击按钮,就可以切换子视图了。

这样写的好处:

多个UIViewController之间切换可以添加动画
当内存警告的时候,可以把当前不是激活状态的ViewController内存释放。
可以把代码更好分开

原文:http://wangjun.easymorse.com/?p=1630

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值