OS5中 UIViewController的parentViewController属性发生了改变

UIViewController的parentViewController属性在iOS5下发生了改变

原来的应用在iOS5下做了调试,发现一个弹出的模式窗口的parentViewController属性一直返回nil,查了一下Apple的文档,发现iOS5下UIViewController的parentViewController属性已经发生了变化,所有模式窗口的parentViewController属性都会返回nil,要获得模式窗口的父窗口,需要使用新的presentingViewController属性,同时增加的还有presentedViewController属性。

相关的AppleSDK说明如下(注意有色的字): 

parentViewController

//当前父视图控制器。 (只读

The parent of thecurrent view controller. (read-only)

//定义视图控制器属性

@property(nonatomic, readonly) UIViewController*parentViewController

Parent viewcontrollers are relevant in navigation, tab bar, and modal viewcontroller hierarchies. In each of these hierarchies, the parent isthe 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 thisproperty is nil.

 

Prior to iOS 5.0,if a view did not have a parent view controller and was beingpresented modally, the view controller that was presenting it wouldbe returned. This is no longer the case. You can get the presentingview controller using the presentingViewControllerproperty.

 

Available in iOS2.0 and later. 

presentedViewController 

The viewcontroller that was presented by this view controller, or one ofits ancestors. (read-only) 

@property(nonatomic, readonly) UIViewController*presentedViewController

Available in iOS5.0 and later. 

presentingViewController

 

The viewcontroller that presented this view controller.(read-only) 

@property(nonatomic, readonly) UIViewController*presentingViewController

The defaultimplementation of this property walks up the view hierarchy,starting from this view controller. The first view controller itfinds that received the presentViewController:animated:completion:method, or that has its definesPresentationContext property set toYES is returned as the value of the property. It keeps walking upthe hierarchy until it finds a value to return or it gets to theroot view controller.

 

原来的问题

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

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

改变

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

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

iOS5之后,对于一个controller,可以通过addChildViewController方法来将一个viewcontroller添加到该viewcontroller上,然后再将view添加到父controller中的view上用来显示。

添加以后,父viewcontroller若响应旋转,相应的子controller也会收到旋转消息。而5.0之前无法做到这一点。相关的新方法还包含presentingcontroller等等。具体的可以参见官方文档的相应部分。 

// The viewcontroller that was presented by this view controller or itsnearest ancestor.

@property(nonatomic,readonly) UIViewController*presentedViewController __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0); 

// The viewcontroller that presented this view controller (or its farthestancestor.)

@property(nonatomic,readonly) UIViewController*presentingViewController__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0);

其中presentedViewController可以获取到由当前controller调用presentModalViewController展示的子视图。  

presentingViewController则可以获取到展示当前controller的父级视图controller。

 

因此在ios5中可以在被展示的视图controller使用以下代码返回上一级视图:

 

[self.presentingViewControllerdismissModalViewController:YES];

 

 

iOS5中UIViewController新方法的使用

在iOS5中,ViewController中新添加了下面几个方法:

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

 

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

iOS5中 <wbr>UIViewController的parentViewController属性发生了改变

 

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

1、创建基于Empty Application的空项目,命名为changeViewController。使用ARCxib

2、添加相应的viewController,共四个控制器类,分别命名为MainViewControllerFirstViewControllerSecondViewControllerThirdViewController。均继承UIViewController要有.xib文件。如下图所示:

iOS5中 <wbr>UIViewController的parentViewController属性发生了改变

 

3、设计MainViewController.xib介面。主要是添加了三个按钮和一个子View,子View宽度和高度为280*325,我把三个按钮设置成不同的tag,分别是tag=123。调整好位置并设置一下主窗口的背景。如图。

iOS5中 <wbr>UIViewController的parentViewController属性发生了改变

 

4、分别设计好FirstViewController.xibSecondViewController.xibThirdViewController.xib。主要是添加了两个标签,把View的宽度和高度均设置主窗口中对应的280*325,注意视图不要有状态栏,即:设Status Bar= None。否则不能调节大小!调整好位置和背景。如图。

iOS5中 <wbr>UIViewController的parentViewController属性发生了改变

iOS5中 <wbr>UIViewController的parentViewController属性发生了改变

iOS5中 <wbr>UIViewController的parentViewController属性发生了改变

 

 

 

5、把MainViewController类添加到window中。在代理AppDelegate.m中,先声明添加如下代码:

#import "MainViewController.h"

然后在- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions方法中把MainViewController类添加到window中:代码如下:

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

{

   self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

   // Override point for customizationafter application launch.

   MainViewController*mainViewController=[[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];

   self.window.rootViewController=mainViewController;

   //self.window.backgroundColor =[UIColor whiteColor];

   [self.window makeKeyAndVisible];

   return YES;

}

这些代码大家都非常了解了,不用多解释。

6、在MainViewController.h中添加三个按钮和子ViewIBOutlet,并且连接一个onClickbutton方法。分别命名为firstButton、secondButton、thirdButon和contentView。方法大家都非常了解了,给一张图:

 

同时声明一个控制器属性UIViewController *currentViewController。最后的MainViewController.h文件代码是这样的:

#import <UIKit/UIKit.h>

@interface MainViewController : UIViewController

{

   

   IBOutlet UIView *contentView;

   IBOutlet UIButton *firstButton;

   IBOutlet UIButton *secondButton;

   IBOutlet UIButton *thirdButon;

    

  UIViewController*currentViewController;

   

}

- (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 *)nibNameOrNilbundle:(NSBundle*)nibBundleOrNil

{

   self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

   if (self) {

       // Custominitialization

   }

   return self;

}

//添加三个子controller代码:

- (void)viewDidLoad

{

   [super viewDidLoad];

   // Do any additional setup afterloading 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; 

- (void)viewDidUnload

{

   firstButton = nil;

   secondButton = nil;

   thirdButon = nil;

   contentView = nil;

   [super viewDidUnload];

   // Release any retained subviews ofthe main view.

   // e.g. self.myOutlet =nil;

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

{

   return (interfaceOrientation ==UIInterfaceOrientationPortrait);

}

这里,要把其中的一个子controllerview添加到根视图中,这样才能显示出相应的视图。本例是把第三个子视图控制器加入的。用的是[contentViewaddSubview:thirdViewController.view];这行代码!

 

8、点击按钮,切换视图。onClickbutton方法的实现,代码如下:

- (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&&[sendertag]==1)||(currentViewController==secondViewController&&[sendertag]==2) ||(currentViewController==thirdViewController&&[sendertag]==3) ) {

           return;

       }

       UIViewController*oldViewController=currentViewController;

       switch ([sender tag]) {

           case 1:

           {

              // NSLog(@"留言及回复");

               [self transitionFromViewController:currentViewController toViewController:firstViewControllerduration:4 options:UIViewAnimationOptionTransitionFlipFromLeftanimations:^{

               } completion:^(BOOL finished) {

                   if (finished) {

                       currentViewController=firstViewController;

                   }else{

                       currentViewController=oldViewController;

                   }

               }];

           }

               break;

           case 2:

           {

               //NSLog(@"生日提醒");

               [self transitionFromViewController:currentViewController toViewController:secondViewControllerduration:1 options:UIViewAnimationOptionTransitionFlipFromTopanimations:^{

                   

               } completion:^(BOOL finished) {

                   if (finished) {

                       currentViewController=secondViewController;

                   }else{

                       currentViewController=oldViewController;

                   }

               }];

           }

               break;

           case 3:

           {

              // NSLog(@"好友申请");

               [self transitionFromViewController:currentViewController toViewController:thirdViewControllerduration:1 options:UIViewAnimationOptionTransitionFlipFromBottomanimations:^{

                   

               }completion:^(BOOL finished) {

                   if (finished) {

                       currentViewController=thirdViewController;

                   }else{

                       currentViewController=oldViewController;

                   }

               }];

           }

               break;

           default:

               break;

       }

   }

}

@end

其中我把按钮设置成不同的tag了。这时候点击按钮,就可以切换子视图了。这样写的好处:

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

9、测试运行,效果如下图:

iOS5中 <wbr>UIViewController的parentViewController属性发生了改变

 

10、原代码下载地下:

http://m1.mail.sina.com.cn/apps/netdisk/download.php?id=b88a6004741064489f4682f5f67ff119

好了今天OK!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值