[IOS] UIViewController的parentViewController属性
UIViewController的parentViewController属性在iOS5下发生了改变
原来的应用在iOS5下做了调试,发现一个弹出的模式窗口的parentViewController属性一直返回nil,查了一下Apple的文档,发现iOS5下UIViewController的parentViewController属性已经发生了变化,所有模式窗口的parentViewController属性都会返回nil,要获得模式窗口的父窗口,需要使用新的presentingViewController属性,同时增加的还有presentedViewController属性。
相关的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 property.
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 definesPresentationContext property set to YES is returned as the value of the property. It keeps walking up the hierarchy until it finds a value to return or it gets to the root view controller.
原来的问题
这些新增的方法和属性用于改进我们的编程方式。那么让我们先看看以前的对于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掉,以节省内存。
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 __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0);
// The view controller that presented this view controller (or its farthest ancestor.)
@property(nonatomic,readonly) UIViewController *presentingViewController__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0);
其中presentedViewController可以获取到由当前controller调用presentModalViewController展示的子视图。
presentingViewController则可以获取到展示当前controller的父级视图controller。
因此在ios5中可以在被展示的视图controller使用以下代码返回上一级视图:
[self.presentingViewController dismissModalViewController:YES];