2008-09-25 44 views
104

我讀過有關有問題的人viewWillAppear無數的帖子,當你不創建視圖層次只是權。我的問題是我無法弄清楚這意味着什麼。iPhone viewWillAppear中沒有發射

如果我創建了一個RootViewController並且在該控制器上調用addSubView,我期望將添加的視圖連接到viewWillAppear事件。

有沒有人有一個複雜的編程視圖層次結構的例子,成功地在每個級別接收viewWillAppear事件?

蘋果的文檔狀態:

警告:如果屬於視圖控制器視圖直接添加到一個視圖層次結構,視圖控制器將不會收到此消息。如果向視圖層次結構中插入或添加視圖,並且它具有視圖控制器,則應直接將關聯的視圖控制器發送此消息。無法發送視圖控制器此消息將阻止顯示任何關聯的動畫。

問題是,他們沒有描述如何做到這一點。 「直接」是什麼意思?你如何「間接」添加視圖?

我對Cocoa和iPhone相當陌生,所以如果除了基本的Hello World廢話之外還有Apple的有用示例,那將會很不錯。

+0

直到我意識到我是錯誤理解用途的UIViewController子類通常我有這個問題。看看這個問題。 http://stackoverflow.com/questions/5691226/am-i-abusing-uiviewcontroller-subclassing/5691708#comment-6507338 – averydev 2011-04-17 23:26:47

+7

請當心!不再適用於iOS 5!調用viewWillAppear和viewDidAppear自動調用 – 2011-11-10 17:23:51

回答

5

我一直在使用導航控制器。當我想要麼下降到數據的另一級或顯示我的自定義視圖我使用以下命令:

[self.navigationController pushViewController:<view> animated:<BOOL>]; 

當我這樣做,我得到的viewWillAppear功能火災。我認爲這是「間接的」,因爲我自己並沒有調用實際的addSubView方法。我不知道這是否適用於您的應用程序,因爲我無法分辨您是否使用導航控制器,但它可能會提供線索。

27

我遇到了同樣的問題。在將其添加爲子視圖之前,只需將viewWillAppear消息發送給您的視圖控制器即可。 (有它告訴視圖控制器,如果它被動畫顯示或不一個BOOL參數。)

[myViewController viewWillAppear:NO]; 

看RootViewController.m在節拍​​器例子。

(其實,我發現蘋果的示例項目很大還有很多比的HelloWorld多;)

+3

實際上,在將其添加到子視圖後,您應該調用viewWillAppear。否則,IBOutlets/IBActions將不會連線。 – 4thSpace 2009-06-17 15:37:11

+2

是的,事後。從XIB創建子視圖,viewWillAppear沒有被調用。自己調用它,一切正常。 – JOM 2010-02-16 07:03:13

+0

謝謝!這對我來說就是這樣。我通過`[scrollView addSubview:controller.view];`手動添加子視圖。我加了一行`[controller viewWillAppear:NO];`然後瞧!像魅力一樣工作。 – 2010-05-09 18:43:04

1

我不是這個100%肯定,但我認爲,添加視圖到視圖層次直接意味着調用-addSubview:在視圖控制器的視圖上(例如,[viewController.view addSubview:anotherViewController.view]),而不是將新的視圖控制器推到導航控制器的堆棧上。

51

如果您使用導航控制器並設置其委託,則不會調用{Will,Did} {Appear,Disappear}方法。

您需要使用導航控制器委託方法代替:

navigationController:willShowViewController:animated: 
navigationController:didShowViewController:animated: 
1

我認爲增加一個子視圖並不一定意味着該視圖會出現,所以沒有對類的方法自動呼叫它會

7

我剛剛有同樣的問題。在我的應用程序中,我有2個導航控制器,並推動相同的視圖控制器在他們每個工作在一個案件,而不是在另一個。我的意思是,當在第一個UINavigationController中推送完全相同的視圖控制器時,viewWillAppear被調用,但在第二個導航控制器中被推入時不會被調用。

然後,我遇到了這個職位UINavigationController should call viewWillAppear/viewWillDisappear methods

,並意識到,我的第二個導航控制器做了重新定義viewWillAppear。篩選的代碼表明,我沒有打電話

[super viewWillAppear:animated]; 

我添加它和它的工作!

文檔說:

如果重寫此方法,您必須在您執行某些時候調用超。

1

我認爲他們的意思是「直接」,就是通過與xcode「導航應用程序」模板相同的方式將事物掛鉤,它將UINavigationController設置爲應用程序UIWindow的唯一子視圖。

使用該模板是我能夠在UINavigationController中的這些控制器的推/拉彈出時獲得在對象ViewControllers上調用的Will/Did/Appear/Disappear方法的唯一方法。這裏的答案中沒有其他解決方案適用於我,包括在RootController中實現它們並將它們傳遞給(子)NavigationController。在顯示/隱藏頂層VC,我的「登錄」和navigationVCs,而不是導航控制器中的子VC之後,這些功能(將/出現/消失)僅在我的RootController中調用,所以我沒有機會「通過他們」到導航VC。

我最終使用UINavigationController的代理功能來查找需要後續功能的特定轉換,並且這種轉換能夠正常工作,但它需要更多的工作才能同時獲得消失和顯示功能「模擬」。

另外這是一個原則性的問題,在今天將這個問題撞上這個問題幾個小時後讓它工作。任何使用自定義RootController和子導航VC的工作代碼片段將非常感謝。

1

如果這有助於任何人。我有一個類似的問題,我的ViewWillAppear未在UITableViewController上發射。經過大量玩耍後,我意識到問題在於控制我的UITableViewUINavigationController不在根視圖上。一旦我解決這個問題,它現在像一個冠軍。

3

通過調用[view addSubview:subview]「直接」添加視圖。 通過交換子視圖的選項卡欄或導航欄等方法「間接」添加視圖。

任何時候你打電話[view addSubview:subviewController.view],你應該打電話[subviewController viewWillAppear:NO](或YES作爲你的情況)。

當我在遊戲中爲子屏幕實現我自己的自定義根視圖管理系統時,我遇到了這個問題。手動添加呼叫viewWillAppear治好了我的問題。

1
[self.navigationController setDelegate:self]; 

將委託設置爲根視圖控制器。

3

由於沒有答案被接受,人們(像我一樣)降落在這裏,我給我的變化。雖然我不確定這是最初的問題。當導航控制器添加作爲一個子視圖到另一個視圖,你必須自己調用viewWillAppear中/ Dissappear等方法是這樣的:

- (void) viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 

    [subNavCntlr viewWillAppear:animated]; 
} 

- (void) viewWillDisappear:(BOOL)animated 
{ 
    [super viewWillDisappear:animated]; 

    [subNavCntlr viewWillDisappear:animated]; 
} 

只是爲了讓這個例子完整。這段代碼出現在我的ViewController中,我創建並將導航控制器添加到我放置在視圖中的視圖中。

- (void)viewDidLoad { 

    // This is the root View Controller 
    rootTable *rootTableController = [[rootTable alloc] 
       initWithStyle:UITableViewStyleGrouped]; 

    subNavCntlr = [[UINavigationController alloc] 
        initWithRootViewController:rootTableController]; 

    [rootTableController release]; 

    subNavCntlr.view.frame = subNavContainer.bounds; 

    [subNavContainer addSubview:subNavCntlr.view]; 

    [super viewDidLoad]; 
} 

的.H看起來像這樣

@interface navTestViewController : UIViewController <UINavigationControllerDelegate> { 
    IBOutlet UIView *subNavContainer; 
    UINavigationController *subNavCntlr; 
} 

@end 

在筆尖文件I具有視圖和該視圖下面我有標籤的圖像和其中i把控制器中的容器(另一個視圖)這裏是它的外觀。我必須爭取一些東西,因爲這是爲客戶做的工作。

alt text

16

我終於找到了解決這個的作品!

UINavigationControllerDelegate

我認爲它的要點是你的導航控制的委託設置到ViewController它在,並實現UINavigationControllerDelegate和它的兩個方法。輝煌!我很激動,我終於找到了解決方案!

4

首先,如Apple文檔中所述,選項卡欄應位於根級別,即添加到窗口。這是正確行爲的關鍵。

其次,你可以使用UITabBarDelegate/UINavigationBarDelegate轉發手動的通知,但我發現,要得到從整體層次要求正常工作,我所要做的就是手動調用

[tabBarController viewWillAppear:NO]; 
[tabBarController viewDidAppear:NO]; 

[navBarController viewWillAppear:NO]; 
[navBarController viewDidAppear:NO]; 

..只是一旦相應的控制器上設置的視圖控制器之前(分配後右)。從此,它在其子視圖控制器上正確調用了這些方法。

我的層次結構是這樣的:

window 
    UITabBarController (subclass of) 
     UIViewController (subclass of) // <-- manually calls [navController viewWill/DidAppear 
      UINavigationController (subclass of) 
       UIViewController (subclass of) // <-- still receives viewWill/Did..etc all the way down from a tab switch at the top of the chain without needing to use ANY delegate methods 

只需調用標籤/導航控制器在第一時間確保所有事件正確轉發上提到的方法。它阻止了我需要從UINavigationBarDelegate/UITabBarControllerDelegate方法手動調用它們。

旁註: 奇怪的是,當它沒有工作,私有方法

- (void)transitionFromViewController:(UIViewController*)aFromViewController toViewController:(UIViewController*)aToViewController 

..你可以從調用堆棧上看到一個工作的實施,通常調用viewWill/Did..的方法,但並沒有到我執行了上述(即使它被稱爲)。

我認爲這是非常重要的UITabBarController是在窗口級別,但文件似乎支持這一點。

希望明確(ish),很樂意回答更多問題。

-3

您應該在任何時候只有1個UIViewController處於活動狀態。任何你想操作的子視圖都應該是 - subVIEWS - 即UIView。

我使用一種簡單的技術來管理我的視圖層次結構,並且由於我以這種方式開始做事,所以還沒有遇到問題。有2個關鍵點:

  • 單一的UIViewController應該用來管理「屏幕的價值」您的應用程序的
  • 使用UINavigationController的改變觀點

這是什麼意思是「一個屏幕的價值「?它的目的有點模糊,但通常它是應用程序的功能或部分。如果你有幾個屏幕具有相同的背景圖像,但不同的疊加/彈出等,應該是1視圖控制器和幾個子視圖。你永遠不應該發現自己使用2個視圖控制器。請注意,如果您希望在多個視圖控制器中顯示屏幕的某些區域,您仍然可以在一個視圖控制器中實例化UIView,並將其添加爲另一個視圖控制器的子視圖。

至於UINavigationController - 這是你最好的朋友!關閉導航欄並將動畫指定爲NO,並且您可以根據需要切換屏幕。如果視圖控制器處於層次結構中,則可以推送和彈出視圖控制器,也可以準備視圖控制器數組(包括包含單個VC的數組),並使用setViewControllers將其設置爲視圖堆棧。這使您可以完全自由地改變VC,同時獲得蘋果預期模式中的所有優勢,並讓所有事件正確啓動。

這是我做的每一次當我啓動的應用程序:從基於窗口的應用程序

  • 開始
  • 添加一個UINavigationController作爲窗口的RootViewController的
  • 添加任何我想我的第一次的UIViewController來作爲nav的根視圖控制器 控制器

(注意從基於窗口的開始只是個人偏好 - 我喜歡自己構建東西,所以我確切知道它們是如何構建的。它應該正常工作的罰款基於視圖的模板)

所有事件火災和基本生活是美好的。然後,您可以將所有時間都花在編寫應用程序的重要部分,而不是嘗試手動將視圖層次結構變形爲形狀。

-1

我不知道這是我解決了同樣的問題。
在某些情況下,方法不能與正常的方式執行的,如「[自methodOne]」。

嘗試

- (void)viewWillAppear:(BOOL)animated 
{ 
    [self performSelector:@selector(methodOne) 
      withObject:nil afterDelay:0]; 
} 
2

我使用push和pop視圖控制器驗證碼:

推:

[self.navigationController pushViewController:detaiViewController animated:YES]; 
[detailNewsViewController viewWillAppear:YES]; 

流行:

[[self.navigationController popViewControllerAnimated:YES] viewWillAppear:YES]; 

..它的工作原理對於我來說足夠了。

1

我只是有這個問題,我和我花了整整3小時(其中谷歌搜索2)進行修復。

原來幫忙的是簡單的從設備/模擬器中刪除應用程序,清理並再次運行

希望幫助

2

一個非常常見的錯誤如下。 你有一種觀點認爲,UIView* a,和一個又一個,UIView* b。 您將b添加到a作爲子視圖。 如果您嘗試在b中調用viewWillAppear,它將永遠不會被解僱,因爲它是子視圖

3

正確的方法是使用UIViewController containment api。

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 
    UIViewController *viewController = ...; 
    [self addChildViewController:viewController]; 
    [self.view addSubview:viewController.view]; 
    [viewController didMoveToParentViewController:self]; 
}