UIViewController的parentViewController属性在iOS5下发生了改变
原来的应用在iOS5下做了调试,发现一个弹出的模式窗口的parentViewController属性一直返回nil,查了一下Apple的文档,发现iOS5下UIViewController的parentViewController属性已经发生了变化,所有模式窗口的parentViewController属性都会返回nil,要获得模式窗口的父窗口,需要使用新的presentingViewController
相关的Apple SDK说明如下(注意有色的字):
parentViewController
//当前父视图控制器。 (只读)
The parent of the current view controller. (read-only)
//定义父视图控制器属性
@property(nonatomic, readonly) UIViewController *parentViewController
Parent view controllers are relevant in navigation, tab bar, and modal view controller hierarchies. In each of these hierarchies, the parent is the object responsible for displaying the current view controller. If you are using a view controller as a standalone object—that is, not as part of a view controller hierarchy—the value in this property is nil.
Prior to iOS 5.0, if a view did not have a parent view controller and was being presented modally, the view controller that was presenting it would be returned. This is no longer the case. You can get the presenting view controller using the presentingViewController
Available in iOS 2.0 and later.
presentedViewController
The view controller that was presented by this view controller, or one of its ancestors. (read-only)
@property(nonatomic, readonly) UIViewController *presentedViewController
Available in iOS 5.0 and later.
presentingViewController
The view controller that presented this view controller. (read-only)
@property(nonatomic, readonly) UIViewController *presentingViewController
The default implementation of this property walks up the view hierarchy, starting from this view controller. The first view controller it finds that received the presentViewController:animated:completion: method, or that has its definesPresentationConte
原来的问题
这些新增的方法和属性用于改进我们的编程方式。那么让我们先看看以前的对于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加进去。需要显示时再调用transitionFromViewContro
另外,当收到系统的Memory Warning的时候,系统也会自动把当前没有显示的subview unload掉,以节省内存。
iOS5之后,对于一个controller,可以通过addChildViewController方法来将一个viewcontroller添加到该viewcontroller上,然后再将view添加到父controller中的view上用来显示。
添加以后,父viewcontroller若响应旋转,相应的子controller也会收到旋转消息。而5.0之前无法做到这一点。相关的新方法还包含presentingcontroller等等。具体的可以参见官方文档的相应部分。
// The view controller that was presented by this view controller or its nearest ancestor.
@property(nonatomic,readonly) UIViewController *presentedViewController
// The view controller that presented this view controller (or its farthest ancestor.)
@property(nonatomic,readonly) UIViewController *presentingViewController
其中presentedViewController可以获取到由当前controller调用presentModalViewControll
presentingViewController
因此在ios5中可以在被展示的视图controller使用以下代码返回上一级视图:
[self.presentingViewController
iOS5中 UIViewController新方法的使用
在iOS5中,ViewController中新添加了下面几个方法:
addChildViewController:
下面详细介绍一下addChildViewController,一个ViewController可以添加多个子ViewController,但是这些子ViewController只有一个是显示到父视图中的,可以通过transitionFromViewContro
下面详细介绍一下上述效果的实现:
1、创建基于Empty Application的空项目,命名为changeViewController。使用ARC和xib。
2、添加相应的viewController,共四个控制器类,分别命名为MainViewController、FirstViewController、SecondViewController、ThirdViewController。均继承UIViewController要有.xib文件。如下图所示:
3、设计MainViewController.xib介面。主要是添加了三个按钮和一个子View,子View宽度和高度为280*325,我把三个按钮设置成不同的tag,分别是tag=1、2、3。调整好位置并设置一下主窗口的背景。如图。
4、分别设计好FirstViewController.xib、SecondViewController.xib、ThirdViewController.xib。主要是添加了两个标签,把View的宽度和高度均设置主窗口中对应的280*325,注意视图不要有状态栏,即:设Status Bar= None。否则不能调节大小!调整好位置和背景。如图。
5、把MainViewController类添加到window中。在代理AppDelegate.m中,先声明添加如下代码:
#import "MainViewController.h"
然后在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOp
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOp
{
}
这些代码大家都非常了解了,不用多解释。
6、在MainViewController.h中添加三个按钮和子View的IBOutlet,并且连接一个onClickbutton方法。分别命名为firstButton、secondButton、thirdButon和contentView。方法大家都非常了解了,给一张图:
同时声明一个控制器属性UIViewController *currentViewController。最后的MainViewController.h文件代码是这样的:
#import <UIKit/UIKit.h>
@interface MainViewController : UIViewController
{
}
- (IBAction)onClickbutton:(id)sender;
@end
7、在MainViewController.m中添加三个子controller。先在#import中添加三个.h文件声明,代码如下:
#import "MainViewController.h"
#import "FirstViewController.h"
#import "SecondViewController.h"
#import "ThirdViewController.h"
然后在- (void)viewDidLoad中添加三个子controller,代码如下:
@interface MainViewController ()
@end
@implementation MainViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
{
}
//添加三个子controller代码:
- (void)viewDidLoad
{
}
- (void)viewDidUnload
{
}
- (BOOL)shouldAutorotateToInterf
{
}
这里,要把其中的一个子controller的view添加到根视图中,这样才能显示出相应的视图。本例是把第三个子视图控制器加入的。用的是[contentView addSubview:thirdViewController.view];这行代码!
8、点击按钮,切换视图。onClickbutton方法的实现,代码如下:
- (IBAction)onClickbutton:(id)sender {
}
@end
其中我把按钮设置成不同的tag了。这时候点击按钮,就可以切换子视图了。这样写的好处:
多个UIViewController之间切换可以添加动画,当内存警告的时候,可以把当前不是激活状态的ViewController内存释放。可以把代码更好分开
9、测试运行,效果如下图:
10、原代码下载地下:
http://m1.mail.sina.com.cn/apps/netdisk/download.php?id=b88a6004741064489f4682f5
好了今天OK!