我正在继承UINavigationController
作为我的应用程序的主要根控制器。视图控制器的目的是提供一个自定义初始屏幕,允许从(从右到左)的滑动操作进入主应用程序。自定义过渡会在滑动过程中淡化初始视图,并显示下面的主应用程序(UITabBarController
)。我的大多数代码都遵循关于iOS7中自定义视图控制器转换的objc.io文章:http://www.objc.io/issue-5/view-controller-transitions.html。
一切似乎都按预期工作。然而,很少,我得到一旦闪屏消失而出现黑屏的报告,而不是主屏幕。我一直无法重现这种行为。这是代码:
首先,在自定义应用委托中设置主根视图控制器:
- (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];
}
来自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;
}
}
以下是我的自定义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
答案 0 :(得分:0)
终于能够复制问题,但仅限于iOS 7.0。通过启动交互式转换,然后取消它,我能够在下一次转换开始时获得黑屏。在完成块中,我需要将fromViewController的alpha值设置回1.再次,这仅在iOS 7.0中是必需的。它不会发生在7.1。