简体   繁体   English

自定义segue将特定的UIViewController推送到UINavigationController

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

I want to create a custom segue that acts in the same way as the standard push segue does when used on UINavigationController view controllers. 我想创建一个自定义segue,其作用方式与在UINavigationController视图控制器上使用时标准push segue相同。 I've implemented my custom segue: 我已经实现了我的自定义segue:

CustomSegue.m 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];
    }

As you can see, the reason I want to use a custom push segue is so that I can decide which view controller to push based on the user configuration (currently only checking a trivial 1==2 expression). 正如您所看到的,我想使用自定义推送segue的原因是我可以根据用户配置决定推送哪个视图控制器(目前只检查一个简单的1 == 2表达式)。 I can instantiate the alternate view controller with no issue, but what I want to be able to do is go back and forth without reloading the view controller each time (using the back and next buttons). 我可以毫无问题地实例化备用视图控制器,但我希望能够做的是每次都不来重新加载视图控制器(使用后退和下一个按钮)。 Is there a way to retrieve an existing instance from the storyboard, or some standard way of doing this? 有没有办法从故事板中检索现有实例,或者这样做的一些标准方法?

Instead of a custom segue with its perform , the way to do what you describe, ie choose in real time whether to push dest or altDest , is either (1) do not use segues at all and just call pushViewController directly as you are doing here, or (2) prepare two segues emanating from the view controller as a whole, and call performSegueWithIdentifier: to say which we should perform. 而不是自定义segue与其perform ,做你所描述的方式,即实时选择是否推动destaltDest ,是(1)根本不使用segues并直接调用pushViewController ,就像你在这里做的一样,或(2)准备从视图控制器整体发出的两个segue,并调用performSegueWithIdentifier:来说明我们应该执行哪些。

As for going directly from dest to altDest , you can push altDest on top of dest and then remove dest from the stack of the navigation controller's view controllers. 至于直接从destaltDest ,你可以在dest顶部推动altDest ,然后从导航控制器的视图控制器的堆栈中删除dest

Like so much about about iOS, this is all so much easier and more obvious if you do not use a storyboard at all. 就像关于iOS一样,如果你根本不使用故事板,这就更容易也更明显了。 This is why I don't like storyboards: they are so simple-minded and limiting, and they distract one's attention from the way iOS really works. 这就是为什么我不喜欢故事板:它们是如此简单和限制,它们分散了人们对iOS 真正工作方式的注意力。

There is no way to retrieve an existing controller from a storyboard -- it would be nice if there were a controllerWithIdentifier: method to do that, but there isn't. 没有办法从故事板中检索现有的控制器 - 如果有一个controllerWithIdentifier:方法来做这件事会很好,但事实并非如此。 Segues (other than unwinds) always instantiate new controllers, so I don't think you can do what you want with a segue. Segues(除了unwinds)总是实例化新的控制器,所以我认为你不能用segue做你想做的事。 If you want to be going forward (push) to the same controller multiple times, then you need to do it in code by creating a property that points to your controller, and checking if that controller exists before pushing to it. 如果你想多次前进(推送)到同一个控制器,那么你需要在代码中通过创建一个指向你的控制器的属性,并在推送它之前检查该控制器是否存在来完成它。

As the others have pointed out, you can't use a segue to push to an existing instance of a controller. 正如其他人所指出的那样,你不能使用segue来推送到现有的控制器实例。 The process of performing a segue always creates a new instance the destination controller for you. 执行segue的过程总是为您创建一个新的实例作为目标控制器。

Personally, when I'm jumping between existing instances of view controllers, I think "container view controller", such as a UIPageViewController , which makes it really easy to transition between two or more controllers, without necessarily reinstantiating them every time. 就个人而言,当我在视图控制器的现有实例之间跳转时,我认为“容器视图控制器”,例如UIPageViewController ,这使得在两个或更多控制器之间转换非常容易,而不必每次都重新实例化它们。

If you don't like the constraints the page view controller imposes (eg maybe you don't like the fact that iOS 5 version only supports page curl transitions, or that iOS 6 only adds the scroll transition, and you want something else), then you'd do a custom container view controller. 如果您不喜欢页面视图控制器所施加的约束(例如,您可能不喜欢iOS 5版本仅支持页面卷曲过渡,或者iOS 6仅添加滚动过渡,并且您想要其他内容),然后你会做一个自定义容器视图控制器。

For example, if I wanted to jump between two view controllers and not reinstantiate them every time, I'd first create a custom container view controller, the "parent", and make sure I have a property to keep track of which child I'm currently at: 例如,如果我想在两个视图控制器之间跳转而不是每次都重新实例化它们,我首先要创建一个自定义容器视图控制器,即“父”,并确保我有一个属性来跟踪哪个孩子我'我目前在:

@property (nonatomic) NSInteger childViewIndex;

If supporting iOS 6.0 and above only, I'd then add a "container view" to my parent view controller's scene. 如果仅支持iOS 6.0及更高版本,我会在父视图控制器的场景中添加“容器视图”。 If supporting iOS versions prior to 6.0, I'd add a standard UIView to the scene and then manually instantiate the first child controller: 如果支持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;
}

Then, when I want to transition to the second child (or transition back to the first child), I'd call the following routine in the parent view 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;
}

Thus, to transition to the second child view controller, you could simply call: 因此,要转换到第二个子视图控制器,您只需调用:

[self transitionToViewControllerIndex:1];

If you want to transition back, you could call: 如果您想转换回来,可以致电:

[self transitionToViewControllerIndex:0];

I'm only scratching the surface here, but container view controllers (or if none of the standard ones do the job for you, a custom container view controller) is precisely what you need. 我只是在这里表面,但容器视图控制器(或者如果没有标准的那些为您完成工作,自定义容器视图控制器)正是您所需要的。

For more information, see: 有关更多信息,请参阅:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 UINavigationController Push Segue-奇怪的动画 - UINavigationController Push Segue - Strange animation 如何用替换的 UINavigationController 推送 UIViewController - How to push UIViewController with replaced UINavigationController 嵌套的UIViewController需要推送到根UINavigationController - Nested UIViewController needs to push onto root UINavigationController UINavigationController的自定义Segue显示黑屏 - Custom Segue to UINavigationController shows black screen 如何使用滑板板将UIViewController推送到iOS5中的UINavigationController? - How to push UIViewController to UINavigationController in iOS5 using stroyboards? 从Storyboard嵌入到容器视图中的UINavigationController不会推送UIViewController - UINavigationController embedded in container view from Storyboard won't push UIViewController 如何让UINavigationController在推送UIViewController时使用翻转动画 - How to have UINavigationController use flip animation while push a UIViewController 自定义Segue推送怪异行为 - Custom Segue push weird behavior 在故事板中使用自定义推送Segue - Using Custom Push Segue in Storyboard 如何以编程方式从一个UIViewController切换到另一个,而无需模态或Push? - How to programmatic segue from one UIViewController to another without Modal or Push?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM