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];