简体   繁体   English

对子类UINavigationController使用自定义iOS 7过渡有时会导致黑屏

[英]Using custom iOS 7 transition with subclassed UINavigationController occasionally results in black screen

I am subclassing a UINavigationController to serve as the main root controller of my application. 我将一个UINavigationController子类化为我的应用程序的主根控制器。 The purpose of the view controller is to present a custom splash screen that allows for a swipe action from (right to left) to enter the main application. 视图控制器的目的是提供一个自定义的启动屏幕,该屏幕允许从(右到左)的滑动操作进入主应用程序。 The custom transition fades the splash view during the swipe and reveals the main application underneath (a UITabBarController ). 自定义过渡会在滑动过程中淡化初始视图,并在下面显示主应用程序( UITabBarController )。 Most of my code is following the objc.io article on custom view controller transitions in iOS7: http://www.objc.io/issue-5/view-controller-transitions.html . 我的大部分代码都遵循关于iOS7中自定义视图控制器转换的objc.io文章: http ://www.objc.io/issue-5/view-controller-transitions.html。

Everything seems to work as expected. 一切似乎都按预期进行。 However, very rarely, I am getting reports of a black screen appearing once the splash screen disappears, instead of the main screen. 但是,很少有我收到有关启动画面消失而不是主画面出现的黑屏的报告。 I have been unable to reproduce the behavior. 我一直无法重现该行为。 Here is the code: 这是代码:

First, setting up the main root view controller in the custom app delegate: 首先,在自定义应用程序委托中设置主根视图控制器:

- (void)applicationDidFinishLaunching:(UIApplication *)application 
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.rootViewController = [[CustomRootViewController alloc] initWithNavigationBarClass:nil toolbarClass:nil];
    self.window.rootViewController = self.rootViewController;
    [self.window makeKeyAndVisible];
}

Important portions from CustomRootViewController (note I'm hiding the navigation bar): CustomRootViewController重要部分(请注意,我隐藏了导航栏):

- (instancetype) initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass
{
    self = [super initWithNavigationBarClass:navigationBarClass toolbarClass:toolbarClass];
    if (self) {
        self.navigationBarHidden = YES;
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.delegate = self;

    // This is the main UI for the app
    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
    CustomTabBarControllerViewController *mainViewController = [mainStoryboard instantiateInitialViewController];
    self.mainViewController = mainViewController;

    UIStoryboard *splashStoryboard = [UIStoryboard storyboardWithName:@"Splash" bundle:[NSBundle mainBundle]];
    SplashViewController *splashViewController = [splashStoryboard instantiateInitialViewController];
    self.splashViewController = splashViewController;

    // Initialize the navigation controller to have the main app sitting under the splash screen
    self.viewControllers = @[self.mainViewController, self.splashViewController];
}

// In the public interface, called from the Splash screen when the user can perform the action
- (void)allowSwipeToDismiss
{
    UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    panGestureRecognizer.delegate = self;
    [self.view addGestureRecognizer:panGestureRecognizer];
}

- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                  animationControllerForOperation:(UINavigationControllerOperation)operation
                                               fromViewController:(UIViewController *)fromVC
                                                 toViewController:(UIViewController *)toVC
{
    if (operation == UINavigationControllerOperationPop) {
        return [[CustomRootViewControllerAnimator alloc ] init];
    }

    return nil;
}

- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
                         interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
{
    return self.interactiveController;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    // Only enable swiping when on the Swipe To Enter screen
    // After we are in the main app, we don't want this gesture recognizer interfering with the rest of the app
    if (self.topViewController == self.splashViewController) {
        return true;
    } else {
        return false;
    }
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        self.interactiveController = [[UIPercentDrivenInteractiveTransition alloc] init];
        [self popViewControllerAnimated:YES];
    } else if (recognizer.state == UIGestureRecognizerStateChanged) {
        CGPoint translation = [recognizer translationInView:self.view];
        CGFloat viewWidth = self.view.bounds.size.width;
        CGFloat percentDone = -translation.x / viewWidth;
        [self.interactiveController updateInteractiveTransition:percentDone];
    } else if (recognizer.state == UIGestureRecognizerStateEnded) {
        if (self.interactiveController.percentComplete < 0.5) {
            [self.interactiveController cancelInteractiveTransition];
        } else {
            [self.interactiveController finishInteractiveTransition];
        }
        self.interactiveController = nil;
    }
}

And here is the code for the CustomRootViewControllerAnimator being returned by my custom UINavigationController: 这是我的自定义UINavigationController返回的CustomRootViewControllerAnimator的代码:

@implementation CustomRootViewControllerAnimator

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
    return 1;
}

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    [[transitionContext containerView] insertSubview:toViewController.view
                                        belowSubview:fromViewController.view];

    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
        fromViewController.view.transform = CGAffineTransformMakeTranslation(-screenWidth, 0);
        fromViewController.view.alpha = 0;
    } completion:^(BOOL finished) {
        fromViewController.view.transform = CGAffineTransformIdentity;
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

@end

Was finally able to replicate the problem, but only in iOS 7.0. 终于能够重现该问题,但仅在iOS 7.0中。 By starting the interactive transition, then canceling it, I was able to get the black screen on the next start of the transition. 通过启动交互式过渡,然后取消它,我可以在过渡的下一个开始时获得黑屏。 In the completion block, I needed to set the alpha value of the fromViewController back to 1. Again, this is only necessary in iOS 7.0. 在完成块中,我需要将fromViewController的alpha值设置回1。同样,这仅在iOS 7.0中是必需的。 It does not happen in 7.1. 在7.1中不会发生。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 自定义过渡导致黑屏或无响应的屏幕 - Custom transition results in black screen or unresponsive screen 从UINavigationController中解除具有自定义转换的UIViewController时出现黑屏 - Black screen when dismissing a UIViewController with custom transition from within a UINavigationController 使用UINavigationController进行iOS 7自定义当前转换 - iOS 7 Custom Present Transition with UINavigationController iOS:模式过渡到黑屏? - iOS: modal transition to a black screen? UINavigationController的自定义Segue显示黑屏 - Custom Segue to UINavigationController shows black screen Xamarin使用自定义UINavigationBar将UINavigationController子类化 - Xamarin subclassed UINavigationController with custom UINavigationBar iOS 7 UINavigationController过渡到UITableView:动画期间为黑色半透明层 - iOS 7 UINavigationController transition to UITableView: black-translucent layer during animation 将背景设置为透明后,iOS UINavigationController显示黑屏 - iOS UINavigationController after setting background to transparent shows black screen iOS应用程序启动黑屏,UINavigationController,Nib,RootViewController - iOS Application launch black screen, UINavigationController, Nib, RootViewController 单击自定义TableView单元格后,UINavigationController显示黑屏 - UINavigationController is showing black screen after clicking on custom TableView cell
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM