我现在正尝试使用iOS 7的自定义视图控制器转换API以交互方式实现解除所呈现的视图控制器.它的工作原理除外,当取消交互式解雇时,自动旋转的处理停止工作. (它会在稍后解除所呈现的视图控制器之后再次工作.)为什么会发生这种情况,我该如何解决这个问题?
编辑:这是您可以运行以演示问题的代码.从下面弹出一个视图,您可以通过向下滑动来消除它.如果通过不完全向下滑动来取消解雇,则呈现视图控制器的视图不再响应旋转,并且呈现的视图控制器的视图具有混乱的布局.
编辑:以下是作为Xcode项目的代码链接:
https://drive.google.com/file/d/0BwcBqUuDfCG2YlhVWE1QekhUWlk/edit?usp=sharing
对于大规模的代码转储感到抱歉,但我不知道我做错了什么.这是一个正在发生的事情的草图:ViewController1呈现ViewController2. ViewController1实现了UIViewControllerTransitioningDelegate,因此它返回了转换的动画/交互式控制器. ViewController2有一个平移手势识别器,可以驱动交互式解雇;它实现了UIViewControllerInteractiveTransitioning作为解雇的交互式控制器.如果用户将视图拖得足够远,它还会保留对动画控制器的引用以解除转换以完成转换.最后,有两个动画控制器对象. PresentAnimationController设置autolayout约束来处理呈现的视图控制器视图的旋转,DismissAnimationController结束解雇.
ViewController1.h
#import <UIKit/UIKit.h> @interface ViewController1 : UIViewController <UIViewControllerTransitioningDelegate> @end
ViewController1.m
#import "ViewController1.h" #import "ViewController2.h" #import "PresentAnimationController.h" #import "DismissAnimationController.h" @implementation ViewController1 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = @"View 1"; self.navigationItem.prompt = @"Press “Present” and then swipe down to dismiss."; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Present" style:UIBarButtonItemStylePlain target:self action:@selector(pressedPresentButton:)]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; // Some subview just to check if layout is working. UIView * someSubview = [[UIView alloc] initWithFrame:self.view.bounds]; someSubview.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; someSubview.backgroundColor = [UIColor orangeColor]; someSubview.layer.borderColor = [UIColor redColor].CGColor; someSubview.layer.borderWidth = 2; [self.view addSubview:someSubview]; } // -------------------- - (void)pressedPresentButton:(id)sender { ViewController2 * presentedVC = [[ViewController2 alloc] initWithNibName:nil bundle:nil]; presentedVC.modalPresentationStyle = UIModalPresentationCustom; presentedVC.transitioningDelegate = self; [self presentViewController:presentedVC animated:YES completion:nil]; } // -------------------- // View Controller Transitioning Delegate Methods. - (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { return [[PresentAnimationController alloc] init];; } - (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed { DismissAnimationController * animationController = [[DismissAnimationController alloc] init]; ViewController2 * presentedVC = (ViewController2 *)self.presentedViewController; if (presentedVC.dismissalIsInteractive) { presentedVC.dismissAnimationController = animationController; } return animationController; } - (id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator { return nil; } - (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator { ViewController2 * presentedVC = (ViewController2 *)self.presentedViewController; if (presentedVC.dismissalIsInteractive) { return presentedVC; } else { return nil; } } @end
ViewController2.h
#import <UIKit/UIKit.h> #import "DismissAnimationController.h" @interface ViewController2 : UIViewController <UIViewControllerInteractiveTransitioning> @property (weak,nonatomic) UIView * contentView; @property (nonatomic,readonly) BOOL dismissalIsInteractive; @property (strong,nonatomic) DismissAnimationController * dismissAnimationController; @end
ViewController2.m
#import "ViewController2.h" @interface ViewController2 () @property (strong,nonatomic) id<UIViewControllerContextTransitioning> transitionContext; @end @implementation ViewController2 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { _dismissalIsInteractive = NO; } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5]; // Set up content view. CGRect frame = UIEdgeInsetsInsetRect(self.view.bounds,UIEdgeInsetsMake(15,15,15)); UIView * contentView = [[UIView alloc] initWithFrame:frame]; self.contentView = contentView; contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; contentView.backgroundColor = [UIColor cyanColor]; contentView.layer.borderColor = [UIColor blueColor].CGColor; contentView.layer.borderWidth = 2; [self.view addSubview:contentView]; // Set up pan dismissal gesture recognizer. UIPanGestureRecognizer * panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dismissalPan:)]; [self.view addGestureRecognizer:panGesture]; } // -------------------- - (void)dismissalPan:(UIPanGestureRecognizer *)panGesture { switch (panGesture.state) { case UIGestureRecognizerStateBegan: { _dismissalIsInteractive = YES; [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; break; } case UIGestureRecognizerStateChanged: { CGPoint translation = [panGesture translationInView:self.view]; CGFloat percent; if (translation.y > 0) { percent = translation.y / self.view.bounds.size.height; percent = MIN(percent,1.0); } else { percent = 0; } // Swiping content view down. CGPoint center; center.x = CGRectGetMidX(self.view.bounds); center.y = CGRectGetMidY(self.view.bounds); if (translation.y > 0) { center.y += translation.y; // Only allow swiping down. } self.contentView.center = center; self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:(0.5 * (1.0 - percent))]; [self.transitionContext updateInteractiveTransition:percent]; break; } case UIGestureRecognizerStateEnded: // Fall through. case UIGestureRecognizerStateCancelled: { _dismissalIsInteractive = NO; id<UIViewControllerContextTransitioning> transitionContext = self.transitionContext; self.transitionContext = nil; DismissAnimationController * dismissAnimationController = self.dismissAnimationController; self.dismissAnimationController = nil; CGPoint translation = [panGesture translationInView:self.view]; if (translation.y > 100) { // Complete dismissal. [dismissAnimationController animateTransition:transitionContext]; } else { // Cancel dismissal. void (^animations)() = ^() { CGPoint center; center.x = CGRectGetMidX(self.view.bounds); center.y = CGRectGetMidY(self.view.bounds); self.contentView.center = center; self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5]; }; void (^completion)(BOOL) = ^(BOOL finished) { [transitionContext cancelInteractiveTransition]; [transitionContext completeTransition:NO]; }; [UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaSEOut animations:animations completion:completion]; } break; } default: { break; } } } // -------------------- // View Controller Interactive Transitioning Methods. - (void)startInteractiveTransition:(id<UIViewControllerContextTransitioning>)transitionContext { self.transitionContext = transitionContext; } @end
PresentAnimationController.h
#import <Foundation/Foundation.h> @interface PresentAnimationController : NSObject <UIViewControllerAnimatedTransitioning> @end
PresentAnimationController.m
#import "PresentAnimationController.h" #import "ViewController2.h" @implementation PresentAnimationController - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext { UIViewController * fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; ViewController2 * toVC = (ViewController2 *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIView * containerView = [transitionContext containerView]; CGPoint toCenter = fromVC.view.center; CGRect toBounds = fromVC.view.bounds; toVC.view.center = toCenter; toVC.view.bounds = toBounds; [toVC.view layoutIfNeeded]; [containerView addSubview:fromVC.view]; [containerView addSubview:toVC.view]; CGRect contentViewEndFrame = toVC.contentView.frame; CGRect contentViewStartFrame = contentViewEndFrame; contentViewStartFrame.origin.y += contentViewStartFrame.size.height; toVC.contentView.frame = contentViewStartFrame; UIColor * endBackgroundColor = toVC.view.backgroundColor; toVC.view.backgroundColor = [UIColor clearColor]; void (^animations)() = ^() { toVC.contentView.frame = contentViewEndFrame; toVC.view.backgroundColor = endBackgroundColor; }; void (^completion)(BOOL) = ^(BOOL finished) { toVC.view.autoresizingMask = UIViewAutoresizingNone; toVC.view.translatesAutoresizingMaskIntoConstraints = NO; NSLayoutConstraint * centerXConstraint = [NSLayoutConstraint constraintWithItem:toVC.view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:fromVC.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]; NSLayoutConstraint * centerYConstraint = [NSLayoutConstraint constraintWithItem:toVC.view attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:fromVC.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]; NSLayoutConstraint * widthConstraint = [NSLayoutConstraint constraintWithItem:toVC.view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:fromVC.view attribute:NSLayoutAttributeWidth multiplier:1 constant:0]; NSLayoutConstraint * heightConstraint = [NSLayoutConstraint constraintWithItem:toVC.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:fromVC.view attribute:NSLayoutAttributeHeight multiplier:1 constant:0]; [containerView addConstraint:centerXConstraint]; [containerView addConstraint:centerYConstraint]; [containerView addConstraint:widthConstraint]; [containerView addConstraint:heightConstraint]; [transitionContext completeTransition:YES]; }; [UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaSEOut animations:animations completion:completion]; } - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext { return 0.5; } @end
DismissAnimationController.h
#import <Foundation/Foundation.h> @interface DismissAnimationController : NSObject <UIViewControllerAnimatedTransitioning> @end
DismissAnimationController.m
#import "DismissAnimationController.h" #import "ViewController2.h" @implementation DismissAnimationController - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext { ViewController2 * fromVC = (ViewController2 *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController * toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIView * containerView = [transitionContext containerView]; [containerView addSubview:toVC.view]; [containerView addSubview:fromVC.view]; void (^animations)() = ^() { CGRect contentViewEndFrame = fromVC.contentView.frame; contentViewEndFrame.origin.y = CGRectGetMaxY(fromVC.view.bounds) + 15; fromVC.contentView.frame = contentViewEndFrame; fromVC.view.backgroundColor = [UIColor clearColor]; }; void (^completion)(BOOL) = ^(BOOL finished) { if ([transitionContext isInteractive]) { [transitionContext finishInteractiveTransition]; } [transitionContext completeTransition:YES]; }; [UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveLinear animations:animations completion:completion]; } - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext { return 0.5; } @end
AppDelegate.m
#import "AppDelegate.h" #import "ViewController1.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; ViewController1 * vc = [[ViewController1 alloc] initWithNibName:nil bundle:nil]; UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:vc]; self.window.rootViewController = nav; [self.window makeKeyAndVisible]; return YES; } @end