【问题标题】:UIViewController transition - objective-cUIViewController 转换-objective-c
【发布时间】:2012-07-06 23:30:27
【问题描述】:

我有UIViewControllers A 和B,它们分配在AppDelegate。我需要对他们应用过渡。如何在不重新分配和替换UIViews 的情况下传输它们? 此代码从我的UIBarButtonItem 中调用UINavigationController

[UIView transitionFromView:self.view  //UIViewController A
                           toView:appDelegate.secondViewController.view //UIViewController B
                           duration:0.5 
                           options:UIViewAnimationOptionTransitionFlipFromLeft   

此方法替换了我的UIViewControllers 中的UIViews,我可以将它们转回,或者只是不知道该怎么做。你能告诉我怎么做吗?

【问题讨论】:

    标签: objective-c ios uiview uiviewcontroller uiviewanimationtransition


    【解决方案1】:

    我找到了解决问题的方法。此代码适用于 iOS 4.x

    [UIView beginAnimations:@"transition" context:nil];
    [UIView setAnimationDuration:1.0];
    
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown 
                 forView:self.navigationController.view 
                   cache:NO];
    
    [self.navigationController 
    pushViewController:self.alternateView animated:NO];
    
    [UIView commitAnimations];
    

    【讨论】:

      【解决方案2】:

      如果您在 iOS 5 世界中并想在各种视图控制器之间跳转,您可能想追求View Controller Containment。或查看WWDC 2011 session 102

      视图控制器包含基本上假定您有一些父视图控制器来管理多个子控制器之间的导航。在您的情况下,父视图将是一个带有导航栏和按钮的视图。

      更新:

      如果你追求遏制,你可以创建一个父视图控制器,它有一个带有按钮的导航栏。当您加载该视图时,您可以添加第一个子视图。因此viewDidLoad 可能看起来像:

      - (void)viewDidLoad
      {
          [super viewDidLoad];
      
          // this is my model, where I store data used by my view controllers
      
          _model = [[MyModel alloc] init];
      
          // let's create our first view controller
      
          OneViewController *controller = [[OneViewController  alloc] initWithNibName:@"OneViewController"  bundle:nil];
      
          // pass it our model (obviously, `model` is a property that I've set up in my child controllers)
      
          controller.model = _model;
      
          // let's put the new child in our container and add it to the view
      
          [self addChildViewController:controller];
          [self configureChild:controller];
          [self.view addSubview:controller.view];
          [controller didMoveToParentViewController:self];
      
          // update our navigation bar title and the label of the button accordingly
      
          [self updateTitles:controller];
      }
      

      configureChild 只是进行最终配置。为方便起见,我经常会在 IB 中设置一个 UIView(在本例中,称为 childView),用于设置框架,这让我摆脱了手动创建框架的世界,但你可以随心所欲:

      - (void)configureChild:(UIViewController *)controller
      {
          // configure it to be the right size (I create a childView in IB that is convenient for setting the size of the views of our child view controllers)
      
          controller.view.frame = self.childView.frame;
      }
      

      这是触摸导航栏中的按钮时的操作。如果您在第一个控制器中,请设置第二个控制器。如果您在第二个控制器中,请设置第一个:

      - (IBAction)barButtonTouchUpInside:(id)sender 
      {
          UIViewController *currentChildController = [self.childViewControllers objectAtIndex:0];
      
          if ([currentChildController isKindOfClass:[OneViewController class]])
          {
              TwoViewController *newChildController = [[TwoViewController alloc] initWithNibName:@"TwoViewController"  bundle:nil];
              newChildController.model = _model;
              [self transitionFrom:currentChildController To:newChildController];
          }
          else if ([currentChildController isKindOfClass:[TwoViewController class]])
          {
              OneViewController *newChildController = [[OneViewController alloc] initWithNibName:@"OneViewController"  bundle:nil];
              newChildController.model = _model;
              [self transitionFrom:currentChildController To:newChildController];
          }
          else
              NSAssert(FALSE, @"Unknown controller type");
      
      }
      

      这完成了基本的转换(包括各种与收容相关的调用):

      - (void)transitionFrom:(UIViewController *)oldController To:(UIViewController *)newController
      {    
          [self addChildViewController:newController];
          [self configureChild:newController];
      
          [self transitionFromViewController:oldController 
                            toViewController:newController
                                    duration:0.5
                                     options:UIViewAnimationOptionTransitionCrossDissolve
                                  animations:^{
                                      [self updateTitles:newController];
                                  }
                                  completion:^(BOOL finished){
                                      [oldController willMoveToParentViewController:nil];
                                      [oldController removeFromParentViewController];
                                      [newController didMoveToParentViewController:self];
                                  }];
      }
      

      这个方法只是在我们父视图控制器的导航栏中根据选择的子视图设置标题。它还设置按钮以引用其他控制器。

      - (void)updateTitles:(UIViewController *)controller
      {
          if ([controller isKindOfClass:[OneViewController class]])
          {
              self.navigationItemTitle.title = @"First View Controller";  // current title
              self.barButton.title = @"Two";                              // title of button to take me to next controller
          }
          else if ([controller isKindOfClass:[TwoViewController class]])
          {
              self.navigationItemTitle.title = @"Second View Controller"; // current title
              self.barButton.title = @"One";                              // title of button to take me to next controller
          }
          else
              NSAssert(FALSE, @"Unknown controller type");
      }
      

      这一切都假设您将在控制器之间跳转时创建和销毁控制器。我通常这样做,但使用模型对象来存储我的数据,所以我保留我想要的任何数据。

      您说您不想在“不重新分配和替换 UIViews”的情况下执行此操作:如果是这样,您还可以更改上面的代码以预先创建两个子视图控制器并将转换更改为简单地在它们之间跳转:

      - (void)viewDidLoad
      {
          [super viewDidLoad];
      
          // this is my model, where I store data used by my view controllers
      
          _model = [[MyModel alloc] init];
      
          // let's create our first view controller
      
          _controller0 = [[OneViewController  alloc] initWithNibName:@"OneViewController"  bundle:nil];
          _controller0.model = _model;
          [self addChildViewController:_controller0];
          [self configureChild:_controller0];
          [_controller0 didMoveToParentViewController:self];
      
          // let's create our second view controller
      
          _controller1 = [[OneViewController  alloc] initWithNibName:@"OneViewController"  bundle:nil];
          _controller1.model = _model;
          [self addChildViewController:_controller1];
          [self configureChild:_controller1];
          [_controller1 didMoveToParentViewController:self];
      
          // let's add the first view and update our navigation bar title and the label of the button accordingly
      
          _currentChildController = _controller0;
          [self.view addSubview:_currentChildController.view];
          [self updateTitles:_currentChildController];
      }
      
      - (void)transitionFrom:(UIViewController *)oldController To:(UIViewController *)newController
      {    
          [self transitionFromViewController:oldController 
                            toViewController:newController
                                    duration:0.5
                                     options:UIViewAnimationOptionTransitionCrossDissolve
                                  animations:^{
                                      [self updateTitles:newController];
                                  }
                                  completion:^(BOOL finished){
                                      _currentChildController = newController;
                                  }];
      }
      
      - (IBAction)barButtonTouchUpInside:(id)sender 
      {
          UIViewController *newChildController;
      
          if ([_currentChildController isKindOfClass:[OneViewController class]])
          {
              newChildController = _controller1;
          }
          else if ([_currentChildController isKindOfClass:[TwoViewController class]])
          {
              newChildController = _controller0;
          }
          else
              NSAssert(FALSE, @"Unknown controller type");
      
          [self transitionFrom:_currentChildController To:newChildController];
      
      }
      

      我已经看到了这两种方式,所以你可以做任何适合你的事情。

      【讨论】:

      • 罗伯特,感谢您提供的精彩教程!第二个教程是否适用于 iOS 4.3。
      • @TimurMustafaev 遗憾的是,没有。视图控制器包含是一个 iOS5 解决方案。如果需要 iOS 4.3 支持,我可能只有一个视图控制器 presentModalViewControllerpushViewController 去第二个,让第二个 dismissModalViewControllerAnimatedpopViewControllerAnimated 返回第一个,然后接受第二个控制器将在您进入/退出时创建/销毁的现实。 (这真的没什么大不了的;像馅饼一样容易。)
      • 是的,我知道这个解决方案,并且已经实施了。无论如何,谢谢你的帮助:)
      • @jacobronniegeorge 抱歉,我不是故意的。在设计良好的应用程序中,您使用Model-View-Controller 模式,也称为 MVC。这个想法是“模型”(您的各种控制器需要访问的那些公共数据元素)可能有自己的对象。 (另一种方法是将您的模型放入singleton。)
      • @jacobronniegeorge 另见Core App Objects 或谷歌“iOS 模型对象”。
      【解决方案3】:

      请参阅here。你基本上想要实现 UIViewController 包含,这是 iOS5 中的一个新功能。上面提供的链接提供了一些代码和一个 github 项目的链接。

      祝你好运

      t

      【讨论】:

        【解决方案4】:

        试试

        UIViewController* controller1;
        UIViewController* controller2;
        [controller1 transitionFromViewController:controller1 toViewController:controller2 duration:0.5f options:0 animations:nil completion:nil];
        

        如果在 navigationtroller - controller1 之上,那么

        UINavigationController* nav;
        [nav pushViewController:controller2 animated:YES];
        

        【讨论】:

        • 使用transitionFromViewController 是,从文档中引用,“只打算由自定义容器视图控制器的实现调用”。这可能是正确的解决方案,但 Timur 可能想要完成所有其他与视图控制器包含相关的任务。
        • 这适用于 iOS 5++。我需要为 iOS 4.3++ 实现这个
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-11-01
        • 2013-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-15
        相关资源
        最近更新 更多