使用FDFullscreenPopGesture遇到的坑以及解决方法

来源:互联网 发布:计算机二级vb题库2017 编辑:程序博客网 时间:2024/06/14 07:50

最近需要给APP添加手势左滑返回功能,使用了框架FDFullscreenPopGesture,把使用过程中遇到的坑以及解决方法记录下

一、UIWebView无法左滑返回

原因:UIWebView默认是不开启左滑手势返回功能的,需要自己开启;
解决:在viewDidLoad方法里面设置属性fd_interactivePopDisabled为NO;

- (void)viewDidLoad{    [super viewDidLoad];    self.fd_interactivePopDisabled = NO;}

二、UIWebView左滑返回没有成功时或者取消返回时导航栏的title文字为空,不见了

原因:在viewWillDisappear:方法里面UIWebView控件被销毁了;

ScanWebView = nil;

解决:

方法一: 最直接有效

在viewWillDisappear方法里面取消UIWebView控件的销毁;即把这行代码注释掉;ScanWebView = nil;//注释掉

方法二: 比较复杂

在webViewDidFinishLoad方法里面用一个变量保存获取的title文字,在viewWillAppear方法里面设置导航栏的title文字;

1、保存title文字的变量

@property (nonatomic, copy) NSString *titleString; //保存title文字的变量

2、设置导航栏的title文字
- (void)viewWillAppear:(BOOL)animated{ //设置导航栏的title文字    [super viewWillAppear:animated];    self.titleLabel.text = self.titleString;}
3、用变量保存获取到的title文字
- (void)webViewDidFinishLoad:(UIWebView *)webView{ //用变量保存获取到的title文字    NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];    self.titleString = title;}

三、左滑返回没有成功或者取消时,会出现 … 的情况

原因:导航控制器的导航栏默认是有一个返回按钮的;设置属性hidesBackButton为YES就会出现这种情况;

解决:设置属性hidesBackButton为NO,或者直接注释掉这行代码,不进行设置;

self.navigationItem.hidesBackButton = NO;

四、从无NavigationBar到有NavigationBar,手势返回的时候,有NavigationBar的控制器导航栏会变成白色,或者消失不见了;

原因:在滑动的时候显示出错

解决:
viewWillAppear:viewWillDisappear:方法里面添加对是否隐藏NavigationBar的判断;

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(CGFLOAT_MIN * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{    UIViewController *vc = [self.navigationController.viewControllers lastObject];    if (vc.fd_prefersNavigationBarHidden) {        [self.navigationController setNavigationBarHidden:YES animated:NO];    } else {        [self.navigationController setNavigationBarHidden:NO animated:NO];    }});

五、调用系统的发送短信控制器MFMessageComposeViewController时(如使用shareSDK进行短信分享时),右上角没有“取消按钮”,无法返回app

原因:好像被挡住了

解决:添加对控制器是否是MFMessageComposeViewController的判断,是的话添加自己添加一个取消按钮并添加方法的实现,

if ([self isKindOfClass:[MFMessageComposeViewController class]]) {    [self fd_pushViewController:viewController animated:animated];    [[self.viewControllers lastObject] navigationItem].rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(dismissModal:)];    return;}
- (void)dismissModal:(UIButton *)sender{    [[self.viewControllers lastObject] dismissViewControllerAnimated:YES completion:nil];}

以上为使用过程遇到的坑以及解决办法,很多也都是从GitHub搜集而来的,建议多到GitHub去看看;

附上FDFullscreenPopGesture的GitHub链接;

最后贴上在FDFullscreenPopGesture基础上修改后的代码:

// The MIT License (MIT)//// Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to deal// in the Software without restriction, including without limitation the rights// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell// copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in all// copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE// SOFTWARE.#import "UINavigationController+FDFullscreenPopGesture.h"#import <objc/runtime.h>#import <MessageUI/MessageUI.h>@interface _FDFullscreenPopGestureRecognizerDelegate : NSObject <UIGestureRecognizerDelegate>@property (nonatomic, weak) UINavigationController *navigationController;@end@implementation _FDFullscreenPopGestureRecognizerDelegate- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer{    // Ignore when no view controller is pushed into the navigation stack.    if (self.navigationController.viewControllers.count <= 1) {        return NO;    }    // Ignore when the active view controller doesn't allow interactive pop.    UIViewController *topViewController = self.navigationController.viewControllers.lastObject;    if (topViewController.fd_interactivePopDisabled) {        return NO;    }    // Ignore when the beginning location is beyond max allowed initial distance to left edge.    CGPoint beginningLocation = [gestureRecognizer locationInView:gestureRecognizer.view];    CGFloat maxAllowedInitialDistance = topViewController.fd_interactivePopMaxAllowedInitialDistanceToLeftEdge;    if (maxAllowedInitialDistance > 0 && beginningLocation.x > maxAllowedInitialDistance) {        return NO;    }    // Ignore pan gesture when the navigation controller is currently in transition.    if ([[self.navigationController valueForKey:@"_isTransitioning"] boolValue]) {        return NO;    }    // Prevent calling the handler when the gesture begins in an opposite direction.    CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view];    if (translation.x <= 0) {        return NO;    }    return YES;}@endtypedef void (^_FDViewControllerWillAppearInjectBlock)(UIViewController *viewController, BOOL animated);@interface UIViewController (FDFullscreenPopGesturePrivate)@property (nonatomic, copy) _FDViewControllerWillAppearInjectBlock fd_willAppearInjectBlock;@end@implementation UIViewController (FDFullscreenPopGesturePrivate)+ (void)load{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        Class class = [self class];        //viewWillAppear        SEL originalSelector = @selector(viewWillAppear:);        SEL swizzledSelector = @selector(fd_viewWillAppear:);        Method originalMethod = class_getInstanceMethod(class, originalSelector);        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);        BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));        if (success) {            class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));        } else {            method_exchangeImplementations(originalMethod, swizzledMethod);        }        //viewWillDisappear        SEL originalSelector2 = @selector(viewWillDisappear:);        SEL swizzledSelector2 = @selector(fd_viewWillDisappear:);        Method originalMethod2 = class_getInstanceMethod(class, originalSelector2);        Method swizzledMethod2 = class_getInstanceMethod(class, swizzledSelector2);        BOOL success2 = class_addMethod(class, originalSelector2, method_getImplementation(swizzledMethod2), method_getTypeEncoding(swizzledMethod2));        if (success2) {            class_replaceMethod(class, swizzledSelector2, method_getImplementation(originalMethod2), method_getTypeEncoding(originalMethod2));        } else {            method_exchangeImplementations(originalMethod2, swizzledMethod2);        }    });}- (void)fd_viewWillAppear:(BOOL)animated{    // Forward to primary implementation.    [self fd_viewWillAppear:animated];    if (self.fd_willAppearInjectBlock) {        self.fd_willAppearInjectBlock(self, animated);    }    //设置导航的显示/隐藏    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(CGFLOAT_MIN * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{        UIViewController *vc = [self.navigationController.viewControllers lastObject];        if (vc.fd_prefersNavigationBarHidden) {            [self.navigationController setNavigationBarHidden:YES animated:NO];        } else {            [self.navigationController setNavigationBarHidden:NO animated:NO];        }    });}- (void)fd_viewWillDisappear:(BOOL)animated{    [self fd_viewWillDisappear:animated];    //设置导航的显示/隐藏    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(CGFLOAT_MIN * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{        UIViewController *vc = [self.navigationController.viewControllers lastObject];        if (vc.fd_prefersNavigationBarHidden) {            [self.navigationController setNavigationBarHidden:YES animated:NO];        } else {            [self.navigationController setNavigationBarHidden:NO animated:NO];        }    });}- (_FDViewControllerWillAppearInjectBlock)fd_willAppearInjectBlock{    return objc_getAssociatedObject(self, _cmd);}- (void)setFd_willAppearInjectBlock:(_FDViewControllerWillAppearInjectBlock)block{    objc_setAssociatedObject(self, @selector(fd_willAppearInjectBlock), block, OBJC_ASSOCIATION_COPY_NONATOMIC);}@end@implementation UINavigationController (FDFullscreenPopGesture)+ (void)load{    // Inject "-pushViewController:animated:"    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        Class class = [self class];        SEL originalSelector = @selector(pushViewController:animated:);        SEL swizzledSelector = @selector(fd_pushViewController:animated:);        Method originalMethod = class_getInstanceMethod(class, originalSelector);        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);        BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));        if (success) {            class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));        } else {            method_exchangeImplementations(originalMethod, swizzledMethod);        }    });}- (void)fd_pushViewController:(UIViewController *)viewController animated:(BOOL)animated{    if (![self.interactivePopGestureRecognizer.view.gestureRecognizers containsObject:self.fd_fullscreenPopGestureRecognizer]) {        // Add our own gesture recognizer to where the onboard screen edge pan gesture recognizer is attached to.        [self.interactivePopGestureRecognizer.view addGestureRecognizer:self.fd_fullscreenPopGestureRecognizer];        // Forward the gesture events to the private handler of the onboard gesture recognizer.        NSArray *internalTargets = [self.interactivePopGestureRecognizer valueForKey:@"targets"];        id internalTarget = [internalTargets.firstObject valueForKey:@"target"];        SEL internalAction = NSSelectorFromString(@"handleNavigationTransition:");        self.fd_fullscreenPopGestureRecognizer.delegate = self.fd_popGestureRecognizerDelegate;        [self.fd_fullscreenPopGestureRecognizer addTarget:internalTarget action:internalAction];        // Disable the onboard gesture recognizer.        self.interactivePopGestureRecognizer.enabled = NO;    }    // Handle perferred navigation bar appearance.    [self fd_setupViewControllerBasedNavigationBarAppearanceIfNeeded:viewController];    //过滤MessageUI,并且添加取消按钮    if ([self isKindOfClass:[MFMessageComposeViewController class]]) {        [self fd_pushViewController:viewController animated:animated];        [[self.viewControllers lastObject] navigationItem].rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(dismissModal:)];        return;    }    // Forward to primary implementation.    if (![self.viewControllers containsObject:viewController]) {        [self fd_pushViewController:viewController animated:animated];    }}- (void)dismissModal:(UIButton *)sender{    [[self.viewControllers lastObject] dismissViewControllerAnimated:YES completion:nil];}- (void)fd_setupViewControllerBasedNavigationBarAppearanceIfNeeded:(UIViewController *)appearingViewController{    if (!self.fd_viewControllerBasedNavigationBarAppearanceEnabled) {        return;    }    __weak typeof(self) weakSelf = self;    _FDViewControllerWillAppearInjectBlock block = ^(UIViewController *viewController, BOOL animated) {        __strong typeof(weakSelf) strongSelf = weakSelf;        if (strongSelf) {            [strongSelf setNavigationBarHidden:viewController.fd_prefersNavigationBarHidden animated:animated];        }    };    // Setup will appear inject block to appearing view controller.    // Setup disappearing view controller as well, because not every view controller is added into    // stack by pushing, maybe by "-setViewControllers:".    appearingViewController.fd_willAppearInjectBlock = block;    UIViewController *disappearingViewController = self.viewControllers.lastObject;    if (disappearingViewController && !disappearingViewController.fd_willAppearInjectBlock) {        disappearingViewController.fd_willAppearInjectBlock = block;    }}- (_FDFullscreenPopGestureRecognizerDelegate *)fd_popGestureRecognizerDelegate{    _FDFullscreenPopGestureRecognizerDelegate *delegate = objc_getAssociatedObject(self, _cmd);    if (!delegate) {        delegate = [[_FDFullscreenPopGestureRecognizerDelegate alloc] init];        delegate.navigationController = self;        objc_setAssociatedObject(self, _cmd, delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);    }    return delegate;}- (UIPanGestureRecognizer *)fd_fullscreenPopGestureRecognizer{    UIPanGestureRecognizer *panGestureRecognizer = objc_getAssociatedObject(self, _cmd);    if (!panGestureRecognizer) {        panGestureRecognizer = [[UIPanGestureRecognizer alloc] init];        panGestureRecognizer.maximumNumberOfTouches = 1;        objc_setAssociatedObject(self, _cmd, panGestureRecognizer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);    }    return panGestureRecognizer;}- (BOOL)fd_viewControllerBasedNavigationBarAppearanceEnabled{    NSNumber *number = objc_getAssociatedObject(self, _cmd);    if (number) {        return number.boolValue;    }    self.fd_viewControllerBasedNavigationBarAppearanceEnabled = YES;    return YES;}- (void)setFd_viewControllerBasedNavigationBarAppearanceEnabled:(BOOL)enabled{    SEL key = @selector(fd_viewControllerBasedNavigationBarAppearanceEnabled);    objc_setAssociatedObject(self, key, @(enabled), OBJC_ASSOCIATION_RETAIN_NONATOMIC);}@end@implementation UIViewController (FDFullscreenPopGesture)- (BOOL)fd_interactivePopDisabled{    return [objc_getAssociatedObject(self, _cmd) boolValue];}- (void)setFd_interactivePopDisabled:(BOOL)disabled{    objc_setAssociatedObject(self, @selector(fd_interactivePopDisabled), @(disabled), OBJC_ASSOCIATION_RETAIN_NONATOMIC);}- (BOOL)fd_prefersNavigationBarHidden{    return [objc_getAssociatedObject(self, _cmd) boolValue];}- (void)setFd_prefersNavigationBarHidden:(BOOL)hidden{    objc_setAssociatedObject(self, @selector(fd_prefersNavigationBarHidden), @(hidden), OBJC_ASSOCIATION_RETAIN_NONATOMIC);}- (CGFloat)fd_interactivePopMaxAllowedInitialDistanceToLeftEdge{#if CGFLOAT_IS_DOUBLE    return [objc_getAssociatedObject(self, _cmd) doubleValue];#else    return [objc_getAssociatedObject(self, _cmd) floatValue];#endif}- (void)setFd_interactivePopMaxAllowedInitialDistanceToLeftEdge:(CGFloat)distance{    SEL key = @selector(fd_interactivePopMaxAllowedInitialDistanceToLeftEdge);    objc_setAssociatedObject(self, key, @(MAX(0, distance)), OBJC_ASSOCIATION_RETAIN_NONATOMIC);}@end
2 0
原创粉丝点击