2009-06-05 52 views
21

我有一個tabBarController與兩個選項卡,其中第一個包含NavigatorController的實例。 navigatorController由一個自定義viewController「peersViewController」啓動,該列表列出了tableView上的所有網絡對等點。選擇對等體後,將「FilesListViewController」(列出c:\目錄中的文件)實例推送到navigationController堆棧中。UINavigationController popToRootViewController,然後立即推新視圖

在這個filesListViewController我有一個按鈕,讓它導航到說文檔目錄。要做到這一點,我想有線接口調用gotoDirectory:(的NSString *)在RootViewController的路徑方法:

- (void)gotoDirectory:(NSString*)path { 
    [[self navigationController] popToRootViewControllerAnimated:YES]; 
    NSArray *files = [self getFilesFromPeerAtPath:path]; 
    FilesListViewController *filesVC = [[FilesListViewController alloc] initWithFiles:files]; 
    [[self navigationController] pushViewController:filesVC animated:YES]; 
    [filesVC release]; 
} 

然而,當我按下該按鈕時,navigationController並彈出我認爲到根視圖控制器,但是然後我實例化的FilesListViewController沒有出現。從日誌中,我知道自定義的initWithFiles方法確實被調用,並且網絡資料確實發生了獲取文件名。

其他的東西對此很詭異。我嘗試點擊第二個標籤,然後點擊回到第一個標籤,然後點擊huala!我需要的文件名在那裏。它看起來像數據和filesListViewController確實被推入navigatorController堆棧,但顯示不刷新,但卡在rootViewController(peersViewController)的屏幕上。

我做錯了什麼?

- 本。

- 發佈問題後15分鐘編輯。我找到了一個解決方法,但它困擾我流行,然後推動不起作用。

- (void)gotoDirectory:(NSString*)path { 
    PeersListViewController *rootViewController = (PeersListViewController*)[[[self navigationController] viewControllers] objectAtIndex:0]; 
    [[self navigationController] setViewControllers:[NSArray arrayWithObject:rootViewController]]; 
    FilesListViewController *filesVC = [[FilesListViewController alloc] initWithFiles:files]; 
    [[self navigationController] pushViewController:filesVC animated:YES]; 
    [filesVC release]; 
} 

它似乎並不像navigationController應該規避這種方式,我可能不得不釋放所有在原始堆棧中的viewControllers。然而,這在iPhone 3.0模擬器上工作。

如果我使用這段代碼,應該如何處理內存釋放?我應該得到視圖控制器的原始NSArray並釋放一切嗎?

回答

10

我得到了一個非常類似的問題(但沒有使用標籤)。我有三個viewController:主(根),窗體和結果。 當UINavigationController的堆棧是

「主 - >結果」

在btnClick我做popToRootViewControllerAnimated則formViewCtrl的按壓。 纔能有

「主 - >形式」

導航欄標題和後退按鈕的標籤是正確的,formViewCtrl的事件被調用。 但是,我仍然看到主視圖。

這裏是我的「解決方案」

做一些測試後,我發現沒有動畫去rootViwCtrl這項工作很好。所以我只使用動畫來推送viewCtrl。

iPhone 3。0,在設備&模擬器上發現問題。

如果我有新的東西,我會更新/評論我的帖子。

+2

是的,你需要彈出沒有動畫(以便它馬上發生),然後推動動畫。如果您試圖一起做兩個動畫更改(需要時間才能完成),則視圖將處於不良狀態。 – Jason 2009-11-18 19:09:01

+0

完全如上所述,這對我不起作用。 我認爲這是堆棧更改的時間問題(Apple的動畫代碼非常脆弱,實施效果不佳) - 這種技術可能會也可能不會工作,取決於屏幕上的其他內容。 – Adam 2009-11-22 22:02:26

1

我找到了一個解決方法,但我無法解釋它爲什麼工作: 1.首先推動所需的控制器。 2.然後彈出到你想要的。

這是完全不合邏輯的,但它適用於我的情況。 爲了清楚起見,我在以下場景中使用它: 第一屏幕 - >進入加載屏幕 - >第二屏幕 當我在第二屏幕上時,我不想要加載屏幕在堆棧中,當點擊後,我應該去第一屏幕。

問候, Vesko科列夫

+0

這真的不應該工作。但它確實如此。 在3.0中,我發現經典的方法(直接操作viewControllers數組)並不總是按預期工作,所以我正在嘗試這種解決方法。 – Adam 2009-11-22 21:59:07

76

的問題,解決這個問題其實是非常簡單的。

調用[self.navigationController popToRootViewControllerAnimated:YES]self.navigationControllernil。當您隨後致電[self.navigationController pushViewController:someOtherViewController]時,您實際上正在向nil發送消息,該消息什麼也不做。

要解決,只需設置一個本地參考navigationController並使用它:

UINavigationController * navigationController = self.navigationController; 
[navigationController popToRootViewControllerAnimated:NO]; 
[navigationController pushViewController:someOtherViewController animated:YES]; 

如前所述由Jason,則必須popToRootViewController沒有動畫執行此才能正常工作。

感謝去jpimbert on the Apple forums指出這一點。

1

尼克街的答案很好,如果你想popToRootViewController並隨後推另一個VC。

VC1 - > VC2 - > VC3:從VC3 => VC2,然後VC1,這裏OK打後退按鈕

然而,當VC1推VC2,這反過來又推動VC3,然後回到VC1直接從VC3爲希望不工作:

我在VC3的-(void)viewWillDisappear:(BOOL)animated實現:

-(void)viewWillDisappear:(BOOL)animated{ 

    ... 
    [self.navigationController popToRootViewControllerAnimated:YES]; 
} 

我也試圖實現它的「返回」按鈕,同樣的結果:在從點擊返回按鈕VC3回到VC1:它打破。實際的VC是VC1,但導航欄仍然是VC2。使用其他組合,我得到了VC2上的VC1 navBar。一塌糊塗。

洛達提到了一些關於時機。我認爲這是主要問題。我已經嘗試了一些東西,所以也許我錯過了這裏的東西,但是這是爲我工作,在最後:

在VC3:

-(void)viewWillDisappear:(BOOL)animated { 

    [super viewWillDisappear:animated]; 
    // notify VC2 
    [[NSNotificationCenter defaultCenter] postNotificationName:backFromV3 object:self]; 
} 

在VC2:

-(void)viewDidLoad { 

    ... 

    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(backFromV3) 
               name:@"BackFromV3" 
               object:nil]; 
} 

-(void)backFromV3{ 
    [NSTimer scheduledTimerWithTimeInterval:0.5 
           target:self 
           selector:@selector(backToRootViewController) 
           userInfo:nil 
           repeats:NO]; 
} 

-(void)backToVC1 { 
    self.navigationItem.rightBarButtonItem = nil; 
    [self.navigationController popToRootViewControllerAnimated:YES]; 
} 

當然,做必要的清潔。

這裏的計時器很關鍵。如果爲0,則中斷。 0。5似乎沒事。

這對我來說非常合適。有點沉重,但我一直無法找到任何有用的技巧。

1

實際上你可以保持「回去」動畫,接着是「前進」動畫,基本上延遲推動動畫直到彈出動畫完成。這裏有一個例子:

(注意:我的appDelegate中有一個名爲「transitionTo」的NSString變量,它最初設置爲@「」)...首先,將該變量設置爲稍後可以檢測到的NSString。然後,彈出控制器給你一個漂亮的屏幕轉換,回到根:

appDelegate.transitionTo = @"Another"; 
[detailNavigationController popToRootViewControllerAnimated:YES]; 

然後RootViewController的的類中,使用viewDidAppear方法:

-(void)viewDidAppear:(BOOL)animated 
{ 
    AppDelegate *appDelegate =(AppDelegate*) [UIApplication sharedApplication].delegate; 
    if([appDelegate.transitionTo isEqualToString:@"Another"]) 
    { 
     [self transitionToAnotherView]; 
     appDelegate.transitionTo = @""; 
    } 
} 

-(void)transitionToAnotherView 
{ 
    // Create and push new view controller here 
    AnotherViewController *controller = [[AnotherViewController alloc] init]; 

    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Home" style:UIBarButtonItemStyleBordered target:nil action:nil]; 
    [self.navigationItem setBackBarButtonItem:backButton]; 

    [[self navigationController] pushViewController:controller animated:YES]; 
} 

所以基本上,流行到根。當轉換在「viewDidAppear」完成時...然後推入下一個視圖。我碰巧保留一個變量來告訴你你希望轉換到哪個視圖(用@「」表示在我想保留在這個屏幕上的情況下不轉換)。

3

我看到這個關於彈出根目錄然後推新ViewController的問題非常普遍,而且這篇文章被很多人看了,所以我想補充一點,以幫助其他新人,尤其是那些使用Xcode的人4和故事板。

在Xcode 4中,您有一個故事板。假設你有這些視圖控制器:HomeViewController,FirstPageViewController,SecondPageViewController。確保點擊它們中的每一個,並通過轉到實用程序窗格 - >屬性檢查器來命名它們的標識符。我們會說他們被命名爲Home,First和Second。

你是家,那麼你去第一,然後你想能夠去第二,並能夠按下後退按鈕回到家。爲此,您需要在FirstPageViewController中更改您的代碼。

要展開示例,請在故事板中的FirstPageViewController中創建一個按鈕。按住Ctrl鍵將該按鈕拖入FirstPageViewController.m。在那裏,下面的代碼將實現預期的結果:

// Remember to add #import "SecondPageViewController.h" at the top 
    SecondPageViewController *secondView = [self.storyboard instantiateViewContorllerWithIdentifier:@"Second"]; 
    UINavigationController *navigationController = self.navigationController; 
    NSArray *array = [navigationController viewControllers]; 
    // [array objectAtIndex:0] is the root view controller 
    NSArray *viewControllersStack = [NSArray arrayWithObjects:[array objectAtIndex:0], secondView, nil]; 
    [navigationController setViewControllers:viewControllersStack animated:YES]; 

基本上,你抓住了視圖控制器,你想要的次序排列它們在堆棧中,然後具有導航控制器使用該堆棧的導航。這是推動和彈出的另一種選擇。

相關問題