簡體   English   中英

自定義segue將特定的UIViewController推送到UINavigationController

[英]Custom segue to push a specific UIViewController to UINavigationController

我想創建一個自定義segue,其作用方式與在UINavigationController視圖控制器上使用時標准push segue相同。 我已經實現了我的自定義segue:

CustomSegue.m

    -(void)perform {
    UIViewController *source = (UIViewController *)[self sourceViewController];
    UIViewController *dest =(UIViewController *)[self destinationViewController];
    if (1==2 //test) {
        [source.navigationController pushViewController:dest animated:YES];
    }
    else {
        UIViewController *altDest = [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:NULL]
         instantiateViewControllerWithIdentifier:@"alternateView"];
        [source.navigationController pushViewController:altDest animated:YES];
    }

正如您所看到的,我想使用自定義推送segue的原因是我可以根據用戶配置決定推送哪個視圖控制器(目前只檢查一個簡單的1 == 2表達式)。 我可以毫無問題地實例化備用視圖控制器,但我希望能夠做的是每次都不來重新加載視圖控制器(使用后退和下一個按鈕)。 有沒有辦法從故事板中檢索現有實例,或者這樣做的一些標准方法?

而不是自定義segue與其perform ,做你所描述的方式,即實時選擇是否推動destaltDest ,是(1)根本不使用segues並直接調用pushViewController ,就像你在這里做的一樣,或(2)准備從視圖控制器整體發出的兩個segue,並調用performSegueWithIdentifier:來說明我們應該執行哪些。

至於直接從destaltDest ,你可以在dest頂部推動altDest ,然后從導航控制器的視圖控制器的堆棧中刪除dest

就像關於iOS一樣,如果你根本不使用故事板,這就更容易也更明顯了。 這就是為什么我不喜歡故事板:它們是如此簡單和限制,它們分散了人們對iOS 真正工作方式的注意力。

沒有辦法從故事板中檢索現有的控制器 - 如果有一個controllerWithIdentifier:方法來做這件事會很好,但事實並非如此。 Segues(除了unwinds)總是實例化新的控制器,所以我認為你不能用segue做你想做的事。 如果你想多次前進(推送)到同一個控制器,那么你需要在代碼中通過創建一個指向你的控制器的屬性,並在推送它之前檢查該控制器是否存在來完成它。

正如其他人所指出的那樣,你不能使用segue來推送到現有的控制器實例。 執行segue的過程總是為您創建一個新的實例作為目標控制器。

就個人而言,當我在視圖控制器的現有實例之間跳轉時,我認為“容器視圖控制器”,例如UIPageViewController ,這使得在兩個或更多控制器之間轉換非常容易,而不必每次都重新實例化它們。

如果您不喜歡頁面視圖控制器所施加的約束(例如,您可能不喜歡iOS 5版本僅支持頁面卷曲過渡,或者iOS 6僅添加滾動過渡,並且您想要其他內容),然后你會做一個自定義容器視圖控制器。

例如,如果我想在兩個視圖控制器之間跳轉而不是每次都重新實例化它們,我首先要創建一個自定義容器視圖控制器,即“父”,並確保我有一個屬性來跟蹤哪個孩子我'我目前在:

@property (nonatomic) NSInteger childViewIndex;

如果僅支持iOS 6.0及更高版本,我會在父視圖控制器的場景中添加“容器視圖”。 如果支持6.0之前的iOS版本,我會在場景中添加一個標准的UIView ,然后手動實例化第一個子控制器:

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

    UIViewController *controller;

    // add the first child

    UIViewController *controller = [self addChildWithIdentifier:@"One"];
    [self.containerView addSubview:controller.view];
    [controller didMoveToParentViewController:self];
    self.childViewIndex = 0;
}

- (UIViewController *)addChildWithIdentifier:(NSString *)storyboardIdentifier
{
    UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:storyboardIdentifier];
    [self addChildViewController:controller];
    controller.view.frame = self.containerView.bounds;
    controller.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    return controller;
}

然后,當我想轉換到第二個子節點(或轉換回第一個子節點)時,我將在父視圖控制器中調用以下例程:

- (void)transitionToViewControllerIndex:(NSInteger)index
{
    // don't do anything if we're trying to transition to ourselves!

    if (index == self.childViewIndex)
        return;

    // identify the two controllers in question

    UIViewController *sourceController = self.childViewControllers[self.childViewIndex];
    UIViewController *destinationController;

    // if we're asking for page 2, but we only have one defined, then we'll have to instantiate it

    BOOL instantiateDestination = (index == 1 && [self.childViewControllers count] < 2);

    if (instantiateDestination)
        destinationController = [self addChildWithIdentifier:@"Two"];
    else
        destinationController = self.childViewControllers[index];

    // configure the destination controller's frame

    destinationController.view.frame = sourceController.view.frame;

    // if you're jumping back and forth, set the animation appropriate for the
    // direction we're going

    UIViewAnimationOptions options;

    if (index > self.childViewIndex)
    {
        options = UIViewAnimationOptionTransitionFlipFromRight;
    }
    else
    {
        options = UIViewAnimationOptionTransitionFlipFromLeft;
    }

    // now transition to that destination controller

    [self transitionFromViewController:sourceController
                      toViewController:destinationController
                              duration:0.5
                               options:options
                            animations:^{
                                // for simple flip, you don't need anything here,
                                // but docs say this can't be NULL; if you wanted
                                // to do some other, custom annotation, you'd do it here
                            }
                            completion:^(BOOL finished) {
                                if (instantiateDestination)
                                    [destinationController didMoveToParentViewController:self];
                            }];

    self.childViewIndex = index;
}

因此,要轉換到第二個子視圖控制器,您只需調用:

[self transitionToViewControllerIndex:1];

如果您想轉換回來,可以致電:

[self transitionToViewControllerIndex:0];

我只是在這里表面,但容器視圖控制器(或者如果沒有標准的那些為您完成工作,自定義容器視圖控制器)正是您所需要的。

有關更多信息,請參閱:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM