我现在正尝试使用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