使用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
- 使用FDFullscreenPopGesture遇到的坑以及解决方法
- erlang的dialyzer使用中遇到的问题,以及解决方法
- 关于ArrayList使用时常遇到的问题以及解决方法
- 生产环境使用elasticsearch遇到的一些问题以及解决方法
- 使用Ubuntu遇到的问题以及解决方法(持续更新)
- 使用CentOS 遇到的问题以及解决方法(持续更新)
- 使用elasticsearch遇到的一些问题以及解决方法
- 使用elasticsearch遇到的一些问题以及解决方法
- 数据库sql server安装使用遇到的问题以及解决方法
- 使用elasticsearch遇到的一些问题以及解决方法
- 使用elasticsearch遇到的一些问题以及解决方法(不断更新)
- 使用MFC过程中遇到的问题以及解决方法(一)
- 使用MFC过程中遇到的问题以及解决方法(二)
- 使用MFC过程中遇到的问题以及解决方法(三)
- Android Studio 使用中遇到的一些问题以及解决方法
- Ubuntu(17.04)使用过程中遇到的问题以及解决方法
- Android6.0和7.0上遇到的坑以及解决方法
- 今天遇到的几个问题以及解决方法
- Xcode编译报错duplicate symbol _base64Decode in:
- webrtc编译过程
- iOS开发 解决同时使用友盟三方登录 和 微信支付 不走回调的问题
- 260. Single Number III(C++)
- spring-mybaits-oracle项目初接触
- 使用FDFullscreenPopGesture遇到的坑以及解决方法
- 逐步求精
- Python文件管理对相应目录下的进删除、重命名、移动文件等相应操作
- 洗牌
- nginx配置优化提高并发量
- 基于spark SQL之上的检索与排序对比性能测试
- centos 7下安装mysql5.7
- 李彦宏手机界面曝光 竟然安装了UC浏览器
- Java集合---LinkedList源码解析