UIViewController转换 - objective-c

Tim*_*aev 5 objective-c uiviewcontroller uiview uiviewanimationtransition ios

我有UIViewControllersA和B,他们被分配AppDelegate.我需要对它们进行过渡.如何在不重新分配和更换的情况下过境UIViews?这段代码来自我的UIBarButtonItemin UINavigationController:

[UIView transitionFromView:self.view  //UIViewController A
                           toView:appDelegate.secondViewController.view //UIViewController B
                           duration:0.5 
                           options:UIViewAnimationOptionTransitionFlipFromLeft   
Run Code Online (Sandbox Code Playgroud)

这个方法取代UIViews了我UIViewControllers,我可以将它们转回,或者只是不知道该怎么做.你能告诉我怎么做吗?

Rob*_*Rob 4

如果您在 iOS 5 世界中并且想要在各种视图控制器之间跳转,您可能需要追求View Controller Containment。或者查看WWDC 2011 第 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];
}
Run Code Online (Sandbox Code Playgroud)

只是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;
}
Run Code Online (Sandbox Code Playgroud)

如果您触摸导航栏中的按钮,则会执行此操作。如果您使用第一个控制器,请设置第二个控制器。如果您使用第二个控制器,请设置第一个控制器:

- (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");

}
Run Code Online (Sandbox Code Playgroud)

这将执行基本转换(包括各种与遏制相关的调用):

- (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];
                            }];
}
Run Code Online (Sandbox Code Playgroud)

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

- (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");
}
Run Code Online (Sandbox Code Playgroud)

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

您说您不想“在不重新分配和替换 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];

}
Run Code Online (Sandbox Code Playgroud)

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