2011-10-20 64 views
29

在iOS 4.3編碼之前,我發現雖然添加視圖控制器的視圖到[superview addSubView:controller.view]的另一個視圖,但控制器實例不會收到-viewWillAppear/viewDidAppear消息,比我發現同樣的問題某些線程在堆棧溢出。之後,我會根據需要手動撥打-viewWillAppear/-viewDidAppeariOS:iOS 4.3和5.0之間不同的addSubview行爲

但是,在升級到iOS 5.0之後,發生了一些活躍的UIView行爲。最後,我發現,在iOS 5中,在[superview addSubView:controller.view],會自動發送-viewWillAppear/-viewDidAppear消息給控制器實例,再加上我的手動調用,也有每次控制器操作其行爲的兩個複製的消息。

,我也發現了類似的問題:iOS 5 : -viewWillAppear is not called after dismissing the modal in iPad

現在的問題是,搜索蘋果公司的文件後,我沒有找到有關這些問題的任何差異明確的文檔。我甚至想知道這是否是iOS 5.0中的有保證的視圖生命週期行爲。

有誰解決類似的問題,或發現有關這些差異的一些準則。因爲我想在4.x & 5.x iOS中運行我的應用程序。

+1

正如你已經發現,大約只有10%的的iOS 4和iOS 5之間的變化被明確記載。 –

回答

28

在iOS 4中,當從視圖層次結構中添加或刪除視圖時,您必須手動調用-viewWillAppear-viewWillDisappear等。如果正在從窗口層次結構中添加或刪除視圖,這些會在iOS 5中自動調用。幸運的是,iOS 5的在UIViewController的方法,你可以重寫還原行爲回到它如何與iOS 4的工作只是添加到您的UIViewController

-(BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers { 
    return NO; 
} 

這可能是最簡單的方法,只要你支持iOS 4和iOS 5.一旦你放棄對iOS 4的支持,你可能會考慮修改你的代碼,以便在交換視圖時使用更新的方法。

編輯2012年2月5日

顯然,這個功能需要的子視圖控制器被添加到使用addChildViewController:方法的主視圖控制器。此方法在iOS4中不存在,因此您需要執行以下操作:

if ([self respondsToSelector:@selector(addChildViewController:)]) { 
    [self addChildViewController:childViewController]; 
    } 

感謝大家誰更正了我。

+0

非常感謝朋友!!!! –

+0

謝謝,解決了ios4上的問題,但在ios5上viewWillAppear被調用兩次(我從中手動調用一次)不知道爲什麼。 – richy

+1

Richy ..這很奇怪,因爲這個方法在iOS4中被忽略,只能在iOS5中調用。您可能要仔細檢查結果。 – chris

0

通過這種方法你知道哪個OS u使用,並把條件,如果是小於5.0或另一個

[的UIDevice currentDevice] systemVersion]

+0

我知道這種方式做一些幫助。我想更多地瞭解這些差異。 – KrzyCube

9

這可能不是你想要的答案,但我有同樣的問題。

在我的情況,當我添加了一個視圖控制器的視圖到另一個視圖控制器的視圖作爲一個子視圖,子視圖僅在IOS 5.0不iOS的4.X.接收viewWillAppear中

所以我增加了一個討厭的條件。

[self.view addSubview:self.viewController.view]; 
if ([[[UIDevice currentDevice] systemVersion] compare:@"5.0"] == NSOrderedAscending) { 
    [self.viewController viewWillAppear:animated]; 
} 

從安裝iOS 5.0,Apple provides a way to implement custom container view controllers like UINavigationController or UITabController。我認爲這個變化會影響viewWillAppear的調用。

如果我們使用-[UIViewController addChildViewController:]這個問題可能解決的。

+0

我不認爲它與操作系統版本有任何關係。 API保持不變。關於什麼時候viewWillApear/Disappear會被調用,有固定的規則。 http://stackoverflow.com/questions/131062/iphone-viewwillappear-not-firing – zakishaheen

+0

非常感謝您的幫助! :) –

2

它是iOS5的行爲:
viewWillAppear,viewDidAppear,...在iOS5的addSubView後自動執行。
因此對於iOS5,無需手動執行這些方法,因爲需要iOS < 5.0。

的修復可能是:

if ([[UIDevice currentDevice].systemVersion doubleValue] < 5.0) { 
...execute viewWillAppear or other 
} 
0

view{Will,Did}Appearview{Will,Did}Disappear視圖控制器,而不是意見的功能。這些功能由SDK提供的視圖控制器調用,這些視圖控制器應該是其他視圖控制器,例如管理UITabBarControllerUINavigationBarController

如果是自己管理的子視圖控制器,你必須明確地調用這些(以及按照正確的順序 - 儘管你應該有一個很好的理由這樣做)。在解僱模態觀點時沒有得到這些電話的模態觀點僅僅是因爲沒有人可以稱之爲模態觀點。將根視圖控制器封裝在UINavigationController(並且如果需要,隱藏導航欄),然後打開模式視圖控制器。一旦被解僱,或者流行,viewWillAppear將被召喚。

5

上面的答案略有不完整。 假設您有2個視圖控制器,ControllerA和ControllerB。

ControllerA.view已添加到窗口(它是父窗口),並且您想將ControllerB.view添加爲ControllerA的子視圖。

如果您沒有首先將ControllerB作爲ControllerA的子級添加,則自動ForwardAppearanceAndRotationMethodsToChildViewControllers將被忽略,並且您仍然會被iOS5調用,這意味着您將調用您的視圖控制器回調兩次。

實施例ControllerA:

- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers { 
    return NO; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.controllerB = [[ControllerB alloc] initWithNibName:@"ControllerB" bundle:nil]; 

    [self.view addSubview:self.controllerB.view]; 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    [self.controllerB viewWillAppear:animated]; 
} 

在ControllerB NSLogging在viewWillAppear中:

- (void)viewWillAppear:(BOOL)animated 
{ 
    NSLog("@ControllerB will appear"); 
} 

這將導致只的iOS5顯示該消息的NSLog兩次。即您自動ForwardAppearanceAndRotationMethodsToChildViewControllers已被忽略。

爲了解決這個問題,您需要添加controllerB作爲控制器a的子項。

早在ControllerA的類:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.controllerB = [[ControllerB alloc] initWithNibName:@"ControllerB" bundle:nil]; 
    if ([self respondsToSelector:@selector(addChildViewController:)]) 
     [self addChildViewController:self.controllerB]; 

    [self.view addSubview:self.controllerB.view]; 
} 

這將現在的工作預期在這兩個iOS4的和iOS5的,而不訴諸檢查的iOS版本字符串的可怕的黑客,而是檢查。如果函數我們之後可用。

希望這會有所幫助。

相關問題