Я занимался новым API перехода на основе iOS 7 и просматривал все обучающие материалы/документацию, которые мог найти, но я не могу представить, как это отразится на моем конкретном сценарии.
Итак, по сути, я пытаюсь реализовать это UIPanGestureRecognizer в представлении, где я бы прокрутил вверх и перешел на VC, чей вид будет скользить снизу, пока текущее представление будет скользить вверх, когда я вытащу свой палец выше.
У меня нет проблем с выполнением этого без перехода взаимодействия, но как только я реализую взаимодействие (жест панорамы), я не могу завершить переход.
Вот соответствующий код из VC, который соответствует UIViewControllerTransitionDelegate, который необходим для доставки контроллеров аниматора:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"Swipe"]) {
NSLog(@"PREPARE FOR SEGUE METHOD CALLED");
UIViewController *toVC = segue.destinationViewController;
[interactionController wireToViewController:toVC];
toVC.transitioningDelegate = self;
toVC.modalPresentationStyle = UIModalPresentationCustom;
}
}
#pragma mark UIViewControllerTransition Delegate Methods
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController: (UIViewController *)presented presentingController: (UIViewController *)presenting sourceController:(UIViewController *)source {
NSLog(@"PRESENTING ANIMATION CONTROLLER CALLED");
SwipeDownPresentationAnimationController *transitionController = [SwipeDownPresentationAnimationController new];
return transitionController;
}
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
NSLog(@"DISMISS ANIMATION CONTROLLER CALLED");
DismissAnimatorViewController *transitionController = [DismissAnimatorViewController new];
return transitionController;
}
- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator {
NSLog(@"Interaction controller for dimiss method caled");
return interactionController.interactionInProgress ? interactionController:nil;
}
ПРИМЕЧАНИЕ. Взаимодействие осуществляется только для увольнения VC, поэтому в методе взаимодействияControllerForDismissal
Вот код для аниматора увольнения, который отлично работает, когда я нажимаю кнопку, чтобы отменить его:
#import "DismissAnimatorViewController.h"
@implementation DismissAnimatorViewController
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
return 1.0;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
NSTimeInterval duration = [self transitionDuration:transitionContext];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
CGRect initialFrameFromVC = [transitionContext initialFrameForViewController:fromVC];
UIView *containerView = [transitionContext containerView];
CGRect screenBounds = [[UIScreen mainScreen] bounds];
NSLog(@"The screen bounds is :%@", NSStringFromCGRect(screenBounds));
toVC.view.frame = CGRectOffset(initialFrameFromVC, 0, screenBounds.size.height);
toVC.view.alpha = 0.2;
CGRect pushedPresentingFrame = CGRectOffset(initialFrameFromVC, 0, -screenBounds.size.height);
[containerView addSubview:toVC.view];
[UIView animateWithDuration:duration
delay:0
usingSpringWithDamping:0.6
initialSpringVelocity:0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
fromVC.view.frame = pushedPresentingFrame;
fromVC.view.alpha = 0.2;
toVC.view.frame = initialFrameFromVC;
toVC.view.alpha = 1.0;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
@end
Здесь приведен код подкласса UIPercentDrivenInteractiveTransition, который служит в качестве контроллера взаимодействия:
#import "SwipeInteractionController.h"
@implementation SwipeInteractionController {
BOOL _shouldCompleteTransition;
UIViewController *_viewController;
}
- (void)wireToViewController:(UIViewController *)viewController {
_viewController = viewController;
[self prepareGestureRecognizerInView:_viewController.view];
}
- (void)prepareGestureRecognizerInView:(UIView*)view {
UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
gesture.minimumNumberOfTouches = 1.0;
[view addGestureRecognizer:gesture];
}
- (CGFloat)completionSpeed {
return 1 - self.percentComplete;
NSLog(@"PERCENT COMPLETE:%f",self.percentComplete);
}
- (void)handleGesture:(UIPanGestureRecognizer*)gestureRecognizer {
// CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view.superview];
CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view.superview];
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateBegan:
// 1. Start an interactive transition!
self.interactionInProgress = YES;
[_viewController dismissViewControllerAnimated:YES completion:nil];
break;
case UIGestureRecognizerStateChanged: {
// 2. compute the current position
CGFloat fraction = fabsf(translation.y / 568);
NSLog(@"Fraction is %f",fraction);
fraction = fminf(fraction, 1.0);
fraction = fmaxf(fraction, 0.0);
// 3. should we complete?
_shouldCompleteTransition = (fraction > 0.23);
// 4. update the animation controller
[self updateInteractiveTransition:fraction];
NSLog(@"Percent complete:%f",self.percentComplete);
break;
}
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled: {
// 5. finish or cancel
NSLog(@"UI GESTURE RECOGNIZER STATE CANCELED");
self.interactionInProgress = NO;
if (!_shouldCompleteTransition || gestureRecognizer.state == UIGestureRecognizerStateCancelled) {
[self cancelInteractiveTransition];
NSLog(@"Interactive Transition is cancled.");
}
else {
NSLog(@"Interactive Transition is FINISHED");
[self finishInteractiveTransition];
}
break;
}
default:
NSLog(@"Default is being called");
break;
}
}
@end
Еще раз, когда я запускаю код сейчас, и я не промахиваю полностью, чтобы целенаправленно отменить переход, я просто получаю флеш-память, и мне представляется контроллер вида, на который я хочу провести. Это происходит независимо от того, завершен или отменен переход.
Однако, когда я увольняюсь с помощью кнопки, я получаю переход, указанный в моем контроллере представления аниматора.