[英]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
,做你所描述的方式,即实时选择是否推动dest
或altDest
,是(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. 至于直接从dest
到altDest
,你可以在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: 有关更多信息,请参阅:
Creating Custom Container View Controllers in the View Controller Programming Guide for iOS. 在适用于iOS的View Controller编程指南中 创建自定义容器视图控制器 。
Implementing UIViewController Containment in the WWDC 2011 Session Videos (Apple developer ID required). 在WWDC 2011会话视频中 实现UIViewController包含 (需要Apple开发人员ID)。
Implementing a Container View Controller in the UIViewController Class Reference. 在UIViewController类参考中 实现Container View Controller 。
Page View Controllers in the View Controller Catalog for iOS. 适用于iOS的View Controller Catalog中的页面视图控制器 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.