場景
假設(shè)現(xiàn)在有這樣一個場景,我有一個根導(dǎo)航控制器RootNavigationController,它的根視圖控制器ViewController有一個子控制器UINavigationController,這個導(dǎo)航控制器的根控制器是FirstViewController。
在FirstViewController中,添加一個方法使用presentModelViewController的方式跳轉(zhuǎn)到另一個根控制器為NextViewController的UINavigationController

如果NextViewController中獲取它的presentingViewController屬性,結(jié)果得到的是RootNavigationController
2016-12-18 10:34:09.548 PresentVCDemo[27202:22455163] viewDidLoad <RootNavigationController: 0x7ff29f83ba00>
2016-12-18 10:34:09.549 PresentVCDemo[27202:22455163] viewDidLoad <ViewController: 0x7ff29de05870>
2016-12-18 10:34:09.572 PresentVCDemo[27202:22455163] viewDidLoad <UINavigationController: 0x7ff29f022a00>
2016-12-18 10:34:09.573 PresentVCDemo[27202:22455163] viewDidLoad <FirstViewController: 0x7ff29dc0c680>
2016-12-18 10:34:52.785 PresentVCDemo[27202:22455163] Presenting Controller : <RootNavigationController: 0x7ff29f83ba00>
原因
蘋果官方的?ViewController Programming Guide中關(guān)于Presenting a View Controller的部分是這樣說的
The view controller that calls the presentViewController:animated:completion: method may not be the one that actually performs the modal presentation. The presentation style determines how that view controller is to be presented, including the characteristics required of the presenting view controller.
也就是說,在調(diào)用presentViewController:animated:completion:方法時,真正作為跳轉(zhuǎn)的容器并不一定是調(diào)用這個方法的view controller,而是取決于modalPresentationStyle。例如,一個全屏的跳轉(zhuǎn)必須由一個全屏的view controller來完成。如果當(dāng)前的控制器不能滿足,那么系統(tǒng)會自動沿著視圖控制器的層級向上查找。
在我們的層級中,只有兩個UINavigationController是全屏的,因此,這兩個控制器都有可能成為最終跳轉(zhuǎn)的容器??墒菫槭裁醋罱K是RootNavigationController完成了這次跳轉(zhuǎn)而不是FirstViewController的導(dǎo)航控制器呢?
在The View Controller Hierachy關(guān)于Presented View Controller中找到了這樣一句話:
When you present a view controller, UIKit looks for a view controller that provides a suitable context for the presentation. In many cases, UIKit chooses the nearest container view controller but it might also choose the window’s root view controller.
因此,在一開始提到的場景中,UIKit幫我們選擇了UIWindow的根視圖控制器,而不是FirstViewController的導(dǎo)航控制器。
解決
在某些特定的業(yè)務(wù)需求中,我們需要利用presentingViewController拿到FirstViewController的導(dǎo)航控制器。
解決這個需求,我們需要用到一對屬性
@property(nonatomic,assign) BOOL definesPresentationContext;
@property(nonatomic,assign) UIModalPresentationStyle modalPresentationStyle;
modalPresentationStyle屬性決定了將要present的控制器以何種方式展現(xiàn),默認(rèn)值為UIModalTransitionStyleCoverVertical
definesPresentationContext就有點(diǎn)神奇了,他的注釋文檔是這么寫的
Determines which parent view controller's view should be presented over for presentations of type UIModalPresentationCurrentContext. If no ancestor view controller has this flag set, then the presenter will be the root view controller.
簡單來說,如果把一個控制器的definesPresentationContext屬性設(shè)置為YES,那么在需要進(jìn)行UIModalPresentationCurrentContext類型的跳轉(zhuǎn)的時候,UIKit會使用視圖層級內(nèi)的這個控制器來進(jìn)行跳轉(zhuǎn)。
在FirstViewController中加入下面的代碼
[self.navigationController setDefinesPresentationContext:YES];
并在跳轉(zhuǎn)的時候設(shè)置目標(biāo)控制器的modalPresentationStyle
[nav setModalPresentationStyle:UIModalPresentationCurrentContext];
[self presentViewController:nav animated:YES completion:nil];
接下來看一下Log日志
2016-12-18 11:59:20.041 PresentVCDemo[32336:22885768] viewDidLoad <RootNavigationController: 0x7fd6f4810600>
2016-12-18 11:59:20.042 PresentVCDemo[32336:22885768] viewDidLoad <ViewController: 0x7fd6f2c04110>
2016-12-18 11:59:20.052 PresentVCDemo[32336:22885768] viewDidLoad <UINavigationController: 0x7fd6f381ce00>
2016-12-18 11:59:20.052 PresentVCDemo[32336:22885768] viewDidLoad <FirstViewController: 0x7fd6f2f090c0>
2016-12-18 11:59:20.920 PresentVCDemo[32336:22885768] Presenting Controller : <UINavigationController: 0x7fd6f381ce00>
大功告成!現(xiàn)在presentingViewController能夠獲取到我們期望的對象了。