【问题标题】:How properly manually to switch between View Controllers in Storyboard (is iOS)?如何正确手动在 Storyboard 中的视图控制器之间切换(是 iOS)?
【发布时间】:2014-10-28 17:55:11
【问题描述】:

我知道有人问过这个问题,但我不明白。

我正在使用带有 segues 的 Storyboard,因为我的应用导航是直截了当的(我不使用导航控制器)。我的问题是在某些情况下我必须切换回另一个视图控制器(不是我最初来自的那个,而是通过几个视图控制器线性切换)。

此时我使用 unwind segue 并返回控制器。据我了解,我可以在事件 viewDidAppear 上使用 segue(否则它不起作用)。这会导致视图控制器一个接一个地出现,这不是很明智。

我知道有些方法可以手动切换到另一个视图控制器。在那种情况下,我不确定 segue in memory 会发生什么。

那么处理这种情况的推荐方法是什么?

编辑

我想我没有详细描述我的案例:

  1. 我使用手动自定义 segue(缠绕和展开)。
  2. 我的视图控制器逻辑如下:

A -> B -> D

A -> C -> D

A ------> D

在大多数情况下,我会向前和向后移动(1 步)。例如,在少数情况下我必须从 D 到 A 通过 B。我做了 2 次放松来做到这一点。我的问题是,要让 unwind 工作,我必须把它放在 viewDidAppear 事件中(否则它不起作用 - 也有一个问题)。所以我从 D 返回 - 屏幕显示 B 和动画,然后我再次放松并打开 A 动画 - 这不实用而且看起来很糟糕。

所以我想知道我可以不使用 segue 从 D 打开 A(我知道这是可能的)?我想知道这将如何影响 unwind segue。据我了解,它被保存在内存中。如果我再次尝试(从 A 到 B 到 D),我也不确定这是否会破坏 segue 链?

【问题讨论】:

  • 你想从 VCA -> vc B -> VC X 去吗? (哪个与vcB没有segue?)如果是这样,如果当前视图控制器是UiNavigation Controller的一部分,您可以手动呈现视图控制器
  • 我更新了问题 - 我不使用导航控制器。我的应用程序具有特定的外观,如果我可以使用隐藏的导航控制器,我不熟悉。我使用手动 segue 管理。

标签: ios objective-c segue


【解决方案1】:

连接控制器本身的展开转场,当你想返回时调用 performSegueWithIdentifier。如果您想在代码中手动调用前向转场,这与您使用前转转场所做的没有什么不同。何时何地调用 performSegueWithIdentifier 取决于应用程序的逻辑;通常,您会调用它来响应某些用户操作。

【讨论】:

  • 嗨@rdelmar,我已经知道了。我的问题是当我必须放松时。据我了解,我只能向后放松。如果我有 vc A -> vc B -> vc D 我将从 A -> B 和 B -> D 展开。然后我将从 D -> B 和 B -> A 展开。但我需要从 D 展开 - > A 没有让 B 在屏幕上可见。
  • @new2ios,您应该能够直接从 D 展开到 A 而无需经过 B。您是使用 Apple 的展开转场,还是使用自定义转场进行展开?没有理由您必须在 viewDidAppear 中放置一个 unwind segue。你需要提供更多关于你正在做什么的细节,并为你正在做的任何自定义 segues 发布代码。
  • 对不起@rdelmar,我弄得有点乱。实际上我有 2 个场景:第一个我必须跳过 vc A 并在开始时直接进入 vc B - 这是在激活步骤之后(我总是从激活步骤开始 - vc A)。在这里,我通过viewDidAppear 2nd 我需要从 vc D 直接返回到 vc A 跳过 vc B (我之前绕过 vc B)。我不知道 2nd 是否可能,因为 unwind 让我回到以前的 vc。我不知道我是否可以在展开之前手动设置目的地和来源。
  • @new2ios,您可以直接展开到您以前前进路径中的任何先前控制器。你是如何设置你的 unwind segues 的?我再问一次;您是使用标准展开,还是使用您制作的自定义展开?
  • 我在自定义 segue 中使用 :[[self sourceViewController] presentModalViewController:[self destinationViewController] animated:YES];[[self destinationViewController] dismissViewControllerAnimated: YES completion: nil];。实际上,我从更多代码开始,然后删除了自定义转换。所以我想我使用标准的 segue 管理。
【解决方案2】:

如果你使用 UINavigationController 在 vi​​ewController 之间切换,

NSArray *viewControllersStack = [[self navigationController] viewControllers];
UIViewController *controller = viewControllersStack[<needed index>];
[[self navigationController] popToViewController:controller animated:YES];

在视图控制器的任何方法中调用并包含 - (void)viewDidAppear:(BOOL)动画

【讨论】:

  • 我没有使用导航控制器@mityaika07。
【解决方案3】:

在这种情况下,我建议使用自定义动画委托将 UINavigationController 子类化,并在内部这样做:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.delegate = [MainNavigationBarDelegate instance];
}

主 NavigationBarDelegate.h:

@interface MainNavigationBarDelegate : NSObject <UINavigationControllerDelegate, UIViewControllerAnimatedTransitioning>

+ (instancetype)instance;

@end

MainNavigationBarDelegate.m:

#import "MainNavigationBarDelegate.h"

@implementation MainNavigationBarDelegate

+ (instancetype)instance
{
    static MainNavigationBarDelegate *delegate;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        delegate = [[MainNavigationBarDelegate alloc] init];
    });

    return delegate;
}


- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{
    return self;
}

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
    return 0.3;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{ 
    RootViewController *fromViewController = (RootViewController*)[transitionContext     viewControllerForKey:UITransitionContextFromViewControllerKey];
    RootViewController *toViewController = (RootViewController*)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    NSUInteger fromIndex = [toViewController.navigationController.childViewControllers indexOfObject:fromViewController];
    NSUInteger toIndex = [toViewController.navigationController.childViewControllers indexOfObject:toViewController];
    BOOL scrollRight = toIndex > fromIndex;

    // Get the size of the view area. 
    [transitionContext.containerView addSubview:fromViewController.view];
    [transitionContext.containerView addSubview:toViewController.view];


    CGFloat xOrigin;
    if (scrollRight){
        xOrigin = fromViewController.view.frame.size.width;
    }
    else {
        xOrigin = -fromViewController.view.frame.size.width;
    }
    toViewController.view.frame = CGRectMake(xOrigin, toViewController.view.frame.origin.y, toViewController.view.frame.size.width, toViewController.view.frame.size.height);

    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{    
        toViewController.view.frame = CGRectMake(0, toViewController.view.frame.origin.y, toViewController.view.frame.size.width, toViewController.view.frame.size.height);
        fromViewController.view.frame = CGRectMake(-xOrigin, fromViewController.view.frame.origin.y, fromViewController.view.frame.size.width, fromViewController.view.frame.size.height);
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:YES]; 

        if (scrollRight){
            fromViewController.view.frame = CGRectMake(0, fromViewController.view.frame.origin.y, fromViewController.view.frame.size.width, fromViewController.view.frame.size.height);
            [toViewController.navigationController.view addSubview:fromViewController.view];
            [toViewController.navigationController.view sendSubviewToBack:fromViewController.view];
        }
    }];
}



@end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多