从右到左推送动画导致损坏的导航栏 [英] Right To Left Push animation results in corrupted navigation bar

查看:148
本文介绍了从右到左推送动画导致损坏的导航栏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在子类化我的 UINavigationController 执行推从右到左(不正常的行为)与UIRTLNavigationController.m我已经添加在这个问题的底部,得到以下警告:

 嵌套推送动画可能导致导航栏损坏
完成意外状态下的导航转换。导航栏子视图树可能会损坏。

我研究过这些错误,发现一个类阻止你接收它们: https://github.com/Plasma/BufferedNavigationController



我添加了BufferedNavigationController .h和.m到我的项目,将BufferedNavigationController.h中的行更改为:
@interface BufferedNavigationController:UIRTLNavigationController
并将BufferedNavigationController设置为我的 UINavigationController 在IB中的自定义子类。



视图仍然从右向左移动,方法在BufferedNavigationController内调用,但我仍然得到警告关于嵌套和..Navigation栏子视图树可能会损坏..



任何帮助将不胜感激。



UIRTLNavigationController.m

  #importUIRTLNavigationController.h


@implementation UIRTLNavigationController

- (id)initWithRootViewController:(UIViewController *)rootViewController
{
self = [super initWithRootViewController:rootViewController];
if(!self)
return nil;
return self;
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
NSLog(@pushViewController);
//添加viewController和一个没有动画的假控制器。然后用动画弹出假控制器。
UIViewController * fakeController = [[[UIViewController alloc] init] autorelease];
[super setViewControllers:[[self viewControllers] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:viewController,fakeController,nil]] animated:NO];
[super popViewControllerAnimated:animated];
}

- (void)popViewControllerAnimatedStep2:(UIViewController *)viewController
{
//使用动画推送新的顶级控制器
[super pushViewController: viewController animated:YES];
//删除应该被弹出的视图
NSMutableArray * arr = [NSMutableArray arrayWithArray:[self viewControllers]];
[arr removeObjectAtIndex:[[self viewControllers] count] -2];
[super setViewControllers:[NSArray arrayWithArray:arr] animated:NO];
}

- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
NSLog(@popViewControllerAnimated);

if(animated)
{
//保存在弹出操作之后应该在上面的控制器
UIViewController * newTopController = [[self viewControllers] objectAtIndex: [[self viewControllers] count] -2];
//从堆栈中删除它。留下应该弹出的视图
NSMutableArray * arr = [NSMutableArray arrayWithArray:[self viewControllers]];
[arr removeObjectAtIndex:[[self viewControllers] count] -2];
[super setViewControllers:[NSArray arrayWithArray:arr] animated:NO];
//计划下一步
[self performSelector:@selector(popViewControllerAnimatedStep2 :) withObject:newTopController afterDelay:0];
return [arr objectAtIndex:[arr count] -1];
}
return [super popViewControllerAnimated:NO];
}

- (void)dealloc {
[super dealloc];
}


@end


方案

我不知道你是否创建自定义UINavigationController只是执行自定义转换,如果你这样做,有一个更简单的方法来做。如下代码

   - (void)makeMyCustomAnimation {
YourDestinationViewController * destinationController = [YourDestinationViewController
alloc] initWithNib .....]; //添加缺少的代码fot ini

CATransition * transition = [CATransition animation];
transition.duration = .25; //你可以改变这个值来满足你的需要
transition.timingFunction = [CAMediaTimingFunction functionWithName:
kCAMediaTimingFunctionEaseInEaseOut];
// kCAMediaTimingFunctionLinear
// kCAMediaTimingFunctionEaseIn
// kCAMediaTimingFunctionEaseOut
// kCAMediaTimingFunctionEaseInEaseOut
// kCAMediaTimingFunctionDefault

transition.type = kCATransitionPush; // kCATransitionMoveIn
// kCATransitionPush,
// kCATransitionReveal
// kCATransitionFade

transition.subtype = kCATransitionFromRight;
// kCATransitionFromLeft,
// kCATransitionFromRight
// kCATransitionFromTop,
// kCATransitionFromBottom

[self.navigationController.view.layer addAnimation:transition
forKey:kCATransition];

[self.navigationController pushViewController:destinationController animated:NO];

}



通过更改子类型值(我可能设置了错误的子类型值,我保持混合)。



也可以对视图控制器使用相同的方法 pop 。我



如果你想使用segue,只需创建一个自定义segue并覆盖 - (void)perform 方法通过添加前面的代码与一些添加,你必须得到视图控制器与 [self sourceViewController]; [self destinationViewController ];


I'm subclassing my UINavigationController to perform a push from right to left (not normal behavior) with UIRTLNavigationController.m I've added at the bottom of this question and get these warnings:

 nested push animation can result in corrupted navigation bar
 Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.

I've researched about these errors and found a class that prevents you from receiving them: https://github.com/Plasma/BufferedNavigationController

I've added BufferedNavigationController .h and .m to my project, changed the line in BufferedNavigationController.h to: @interface BufferedNavigationController : UIRTLNavigationController and seted BufferedNavigationController to be my UINavigationController custom subclass in the IB.

Views are still moving from right to left , methods are getting called inside BufferedNavigationController but I'm still get the warnings about nested and ..Navigation Bar subview tree might get corrupted..

Any help would be appreciated.

UIRTLNavigationController.m:

#import "UIRTLNavigationController.h"


@implementation UIRTLNavigationController

- (id)initWithRootViewController:(UIViewController *)rootViewController
{
        self = [super initWithRootViewController:rootViewController];
        if (!self)
                return nil;
        return self;
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
        NSLog(@"pushViewController");
        // Add the viewController and a fake controller without animation. Then pop the fake controller with animation.
        UIViewController *fakeController = [[[UIViewController alloc] init] autorelease];
        [super setViewControllers:[[self viewControllers] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:viewController, fakeController, nil]] animated:NO];
        [super popViewControllerAnimated:animated];
}

- (void)popViewControllerAnimatedStep2:(UIViewController *)viewController
{
        // Push the new top controller with animation
        [super pushViewController:viewController animated:YES];
        // Remove the view that should have been popped
        NSMutableArray *arr = [NSMutableArray arrayWithArray:[self viewControllers]];
        [arr removeObjectAtIndex:[[self viewControllers] count]-2];
        [super setViewControllers:[NSArray arrayWithArray:arr] animated:NO];
}

- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
        NSLog(@"popViewControllerAnimated");

        if (animated)
        {
                // Save the controller that should be on top after this pop operation
                UIViewController *newTopController = [[self viewControllers] objectAtIndex:[[self viewControllers] count]-2];
                // Remove it from the stack. Leave the view that should be popped on top
                NSMutableArray *arr = [NSMutableArray arrayWithArray:[self viewControllers]];
                [arr removeObjectAtIndex:[[self viewControllers] count]-2];
                [super setViewControllers:[NSArray arrayWithArray:arr] animated:NO];
                // Schedule the next step
                [self performSelector:@selector(popViewControllerAnimatedStep2:) withObject:newTopController afterDelay:0];
                return [arr objectAtIndex:[arr count]-1];
        }
        return [super popViewControllerAnimated:NO];
}

- (void)dealloc {
    [super dealloc];
}


@end

解决方案

I don't know if you are creating the custom UINavigationController just to perform a custom transition, if you do, there is an easier way to do it. Like the following code

-(void)makeMyCustomAnimation {
      YourDestinationViewController *destinationController = [YourDestinationViewController 
                                                             alloc] initWithNib.....];//add the missing code fot ini

  CATransition* transition = [CATransition animation];
  transition.duration = .25; //you can change this value to fit your needs
  transition.timingFunction = [CAMediaTimingFunction functionWithName: 
                                           kCAMediaTimingFunctionEaseInEaseOut]; 
                                           //kCAMediaTimingFunctionLinear
                                           //kCAMediaTimingFunctionEaseIn
                                           //kCAMediaTimingFunctionEaseOut
                                           //kCAMediaTimingFunctionEaseInEaseOut
                                           //kCAMediaTimingFunctionDefault

   transition.type = kCATransitionPush; //kCATransitionMoveIn;
                                     //kCATransitionPush,  
                                     //kCATransitionReveal
                                     //kCATransitionFade

   transition.subtype = kCATransitionFromRight; 
                       //kCATransitionFromLeft,
                       //kCATransitionFromRight 
                       //kCATransitionFromTop, 
                      //kCATransitionFromBottom

[self.navigationController.view.layer addAnimation:transition
                                                            forKey:kCATransition];

[self.navigationController pushViewController:destinationController animated:NO];

}

You can change the direction of your transition by changing the subtype value.(I might be set the wrong value of the subtype, I keep mixing them)

Also you can use the same approach for pop-ing the view controller. I

And It can be used if you want to use segues, just create a custom segue and overrode the -(void)perform method by adding the previous code with some additions, you have to get the view controllers with [self sourceViewController]; and [self destinationViewController];

这篇关于从右到左推送动画导致损坏的导航栏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆