NewsBlur/clients/ios/Other Sources/SloppySwiper/SloppySwiper.m
David Sinclair d77ddc0161 iOS: fixed remaining Xcode 8 warnings
Now zero warnings on build. Ah, so much cleaner.
2016-10-06 21:18:12 -07:00

124 lines
4.4 KiB
Objective-C
Executable file

//
// SloppySwiper.m
//
// Created by Arkadiusz Holko http://holko.pl on 29-05-14.
//
#import "SloppySwiper.h"
#import "SSWAnimator.h"
#import "SSWDirectionalPanGestureRecognizer.h"
@interface SloppySwiper()
@property (weak, readwrite, nonatomic) UIPanGestureRecognizer *panRecognizer;
@property (weak, nonatomic) IBOutlet UINavigationController *navigationController;
@property (strong, nonatomic) SSWAnimator *animator;
@property (strong, nonatomic) UIPercentDrivenInteractiveTransition *interactionController;
/// A Boolean value that indicates whether the navigation controller is currently animating a push/pop operation.
@property (nonatomic) BOOL duringAnimation;
@end
@implementation SloppySwiper
#pragma mark - Lifecycle
- (void)dealloc
{
[_panRecognizer removeTarget:self action:@selector(pan:)];
[_navigationController.view removeGestureRecognizer:_panRecognizer];
}
- (instancetype)initWithNavigationController:(UINavigationController *)navigationController
{
NSCParameterAssert(!!navigationController);
self = [super init];
if (self) {
_navigationController = navigationController;
[self commonInit];
}
return self;
}
- (void)awakeFromNib
{
[super awakeFromNib];
[self commonInit];
}
- (void)commonInit
{
SSWDirectionalPanGestureRecognizer *panRecognizer = [[SSWDirectionalPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
panRecognizer.direction = SSWPanDirectionRight;
panRecognizer.maximumNumberOfTouches = 1;
[_navigationController.view addGestureRecognizer:panRecognizer];
_panRecognizer = panRecognizer;
_animator = [[SSWAnimator alloc] init];
}
#pragma mark - UIPanGestureRecognizer
- (void)pan:(UIPanGestureRecognizer*)recognizer
{
UIView *view = self.navigationController.view;
if (recognizer.state == UIGestureRecognizerStateBegan) {
if (self.navigationController.viewControllers.count > 1 && !self.duringAnimation) {
self.interactionController = [[UIPercentDrivenInteractiveTransition alloc] init];
self.interactionController.completionCurve = UIViewAnimationCurveEaseOut;
[self.navigationController popViewControllerAnimated:YES];
}
} else if (recognizer.state == UIGestureRecognizerStateChanged) {
CGPoint translation = [recognizer translationInView:view];
// Cumulative translation.x can be less than zero because user can pan slightly to the right and then back to the left.
CGFloat d = translation.x > 0 ? translation.x / CGRectGetWidth(view.bounds) : 0;
[self.interactionController updateInteractiveTransition:d];
} else if (recognizer.state == UIGestureRecognizerStateEnded) {
if ([recognizer velocityInView:view].x > 0) {
[self.interactionController finishInteractiveTransition];
} else {
[self.interactionController cancelInteractiveTransition];
// When the transition is cancelled, `navigationController:didShowViewController:animated:` isn't called, so we have to maintain `duringAnimation`'s state here too.
self.duringAnimation = NO;
}
self.interactionController = nil;
}
}
#pragma mark - UINavigationControllerDelegate
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{
if (operation == UINavigationControllerOperationPop) {
return self.animator;
}
return nil;
}
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
{
return self.interactionController;
}
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (animated) {
self.duringAnimation = YES;
}
}
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
self.duringAnimation = NO;
if (navigationController.viewControllers.count <= 1) {
self.panRecognizer.enabled = NO;
}
else {
self.panRecognizer.enabled = YES;
}
}
@end