【问题标题】:View Controllers: How to switch between views programmatically?视图控制器:如何以编程方式在视图之间切换?
【发布时间】:2010-10-29 00:01:17
【问题描述】:

简而言之:我想要两个全屏视图,我可以在视图 A 和视图 B 之间切换。我知道我可以只使用选项卡栏控制器,但我不想这样做。我想看看这是如何手工完成的,以了解幕后发生的事情。

我有一个 UIViewController 作为根控制器:

@interface MyRootController : UIViewController {
    IBOutlet UIView *contentView;
}
@property(nonatomic, retain) UIView *contentView;

@end

contentView 连接到一个 UIView,我将它作为子视图添加到 Nib 的“视图”中。这有绿色,我看到它全屏。工作正常。

然后,我以几乎相同的方式创建了另外两个视图控制器。 ViewControllerA 和 ViewControllerB。 ViewControllerA 有蓝色背景, ViewControllerB 有黑色背景。只是看看哪个是活跃的。

所以,在 myRootController 的实现中,我这样做:

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    ViewControllerA *vcA = [[ViewControllerA alloc] initWithNib];
    [self.contentView addSubview:vcA.view];

    [cvA release];
}

顺便说一下,-initWithNib 方法是这样的:

- (id)initWithNib { // Load the view nib
    if (self = [super initWithNibName:@"ViewA" bundle:nil]) {
        // do ivar initialization here, if needed
    }
    return self;
}

这行得通。当我启动应用程序时,我会看到来自 ViewControllerA 的视图。但现在最大的问题是:视图控制器通常具有所有这些方法,例如:

  • (void)viewWillAppear:(BOOL)动画;
  • (void)viewDidDisappear:(BOOL)动画;
  • (void)viewDidLoad;

...等等。如果我在没有标签栏控制器的情况下以“我的”方式进行操作,谁或什么,或者如何调用这些方法?我的意思是:如果我分配 ViewController 的类并且视图 get 是可见的,我是否需要注意调用这些方法?它如何知道 viewWillAppear、viewDidDisappear 或 viewDidLoad?我相信标签栏控制器在引擎盖下具有所有这些“聪明”。还是我错了?

更新:我已经测试过了。如果我释放视图控制器(例如:ViewControllerA),我将不会在 viewDidDisappear 上收到任何日志消息。只有在分配和初始化 ViewControllerA 时,我才会得到一个 viewDidLoad。但就是这样。所以现在所有的迹象都代表了 UITabBarController 的聪明;)我必须弄清楚如何复制它,对吧?

【问题讨论】:

    标签: iphone uikit uiviewcontroller uitabbarcontroller


    【解决方案1】:

    在开始 iPhone 开发的第 6 章中有一个很好的切换视图示例。你可以在这里看到它的源代码: http://iphonedevbook.com/

    SwitchViewController 具有以编程方式更改视图的代码。

    
    - (IBAction)switchViews:(id)sender
    {
    
        if (self.yellowViewController == nil)
        {
            YellowViewController *yellowController = [[YellowViewController alloc]
                    initWithNibName:@"YellowView" bundle:nil];
            self.yellowViewController = yellowController;
            [yellowController release];
        }
    
        [UIView beginAnimations:@"View Flip" context:nil];
        [UIView setAnimationDuration:1.25];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    
        UIViewController *coming = nil;
        UIViewController *going = nil;
        UIViewAnimationTransition transition;
    
        if (self.blueViewController.view.superview == nil) 
        {   
            coming = blueViewController;
            going = yellowViewController;
            transition = UIViewAnimationTransitionFlipFromLeft;
        }
        else
        {
            coming = yellowViewController;
            going = blueViewController;
            transition = UIViewAnimationTransitionFlipFromRight;
        }
    
        [UIView setAnimationTransition: transition forView:self.view cache:YES];
        [coming viewWillAppear:YES];
        [going viewWillDisappear:YES];
        [going.view removeFromSuperview];
        [self.view insertSubview: coming.view atIndex:0];
        [going viewDidDisappear:YES];
        [coming viewDidAppear:YES];
    
        [UIView commitAnimations];
    
    }
    

    【讨论】:

    • +1 用于引用您获得示例的位置(正是@iPhoney 忘记做的事情)。
    【解决方案2】:

    你可以从最简单的 removeFromSuperview/insertSubview 开始,一点一点的添加代码。

    
    //SwitchViewController.h
    #import 
    @class BlueViewController;
    @class YellowViewController;
    
    @interface SwitchViewController : UIViewController {
        IBOutlet BlueViewController *blueViewController;
        IBOutlet YellowViewController *yellowViewController;
    }
    - (IBAction)switchViews:(id)sender;
    @property (nonatomic, retain) BlueViewController *blueViewController;
    @property (nonatomic, retain) YellowViewController *yellowViewController;
    @end
    
    
    //1. remove yellow view and insert blue view
    - (IBAction)switchViews:(id)sender {
        if(self.blueViewController.view.superview == nil)
        {
            [yellowViewController.view removeFromSuperview];
            [self.view insertSubview:blueViewController.view atIndex:0];
        }
    }
    
    //2. appear=insert, disappear=remove
    if(blueViewController.view.superview == nil)
    {
        [blueViewController viewWillAppear:YES];
        [yellowViewController viewWillDisappear:YES];
    
        [yellowViewController.view removeFromSuperview];
        [self.view insertSubview:self.blueViewController.view atIndex:0];
    
        [yellowViewController viewDidDisappear:YES];
        [blueViewController viewDidAppear:YES];
    }
    
    //3. now add animation
    [UIView beginAnimations:@"View Flip" context:nil];
    [UIView setAnimationDuration:1.25];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    //blue view will appear by flipping from right
    if(blueViewController.view.superview == nil)
    {
        [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight 
                                forView:self.view cache:YES];
    
        [blueViewController viewWillAppear:YES];
        [yellowViewController viewWillDisappear:YES];
    
        [yellowViewController.view removeFromSuperview];
        [self.view insertSubview:self.blueViewController.view atIndex:0];
    
        [yellowViewController viewDidDisappear:YES];
        [blueViewController viewDidAppear:YES];
    }
    [UIView commitAnimations];
    
    

    【讨论】:

      【解决方案3】:

      如果我理解正确,您要完成的工作非常简单。

      只需在您的应用程序委托上添加一个 UINavigationController 并执行以下操作:

      [navigationController pushView:vcA];
      

      将相应地调用代表:

      • (void)viewWillAppear:(BOOL)动画;
      • (void)viewDidDisappear:(BOOL)动画;
      • (void)viewDidLoad;

      当你想要弹出视图并推送另一个视图时:

      [navigationController popViewControllerAnimated:true];
      [navigationController pushView:vcB];
      

      如果您不想让 navigationController 显示,请使用:

      [navigationBar setHidden:YES];
      

      其中 navigationBar 是你的 UINavigationController 对应的 UINavigationBar。

      【讨论】:

      • 听起来不错,但我不想要任何类型的导航或标签栏;)我只想要带有按钮“转到 B”和另一个“转到 A”的裸视图。或者有没有办法在上面没有那个导航栏?
      • 如果您不希望它显示在屏幕上,您绝对可以隐藏导航栏。我会用信息更新答案。
      【解决方案4】:

      这可能是一个老问题,但我最近遇到了同样的问题,很难找到有效的方法。我想在两个互补的视图控制器之间切换,但我希望切换是动画的(内置动画效果很好),如果可能的话,我希望它与故事板兼容。

      为了利用内置的过渡,UIView 的+transitionFromView:toView:duration:options:completion: 方法工作得很好。但是,它只在视图之间转换,而不是视图控制器。

      要在整个视图控制器之间进行转换,而不仅仅是视图,创建自定义 UIStoryboardSegue 是可行的方法。无论您是否使用故事板,这种方法都可以让您封装整个转换并管理相关信息从一个视图控制器到下一个视图控制器的传递。它只涉及子类化UIStoryboardSegue 并覆盖单个方法-perform

      有关参考实现,请参阅 RAFlipReplaceSegue,这是我使用这种方法组合在一起的确切自定义 segue。作为奖励,如果它在 UINavigationController 堆栈中,它还会用新的视图控制器替换旧的视图控制器。

      【讨论】:

        猜你喜欢
        • 2017-11-30
        • 2014-09-30
        • 2012-06-11
        • 1970-01-01
        • 1970-01-01
        • 2011-05-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多