對之前一直寫一直用的功能石抡,來做個總結(jié)。
系統(tǒng)自帶的pop效果是輕掃左邊邊緣pop返回助泽,要實現(xiàn)的效果是輕掃全屏pop返回啰扛。
思路
要改變系統(tǒng)的效果,1.重寫嗡贺,2.設置系統(tǒng)提供的相關(guān)屬性(直接設置/通過KVC)
探究
首先隐解,我們先去UINavigationController.h源文件中找系統(tǒng)提供的方法或者屬性。@property(nullable, nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
诫睬,interactivePopGestureRecognizer是只讀屬性厢漩,屬于UIGestureRecognizer這個類。因為是readonly的岩臣,所以我們無法重寫和自定義溜嗜,繼續(xù)點進去UIGestureRecognizer.h查看,有一個enabled屬性架谎,所以可以將enabled設置為NO炸宵,或者猜測是否有私有屬性可以通過KVC搞定的。
于是谷扣,log一下interactivePopGestureRecognizer一看究竟
NSLog(@"%@",self.navigationController.interactivePopGestureRecognizer);
打印結(jié)果
<UIScreenEdgePanGestureRecognizer: 0x7fd9a160cb30; state = Possible; enabled = NO; delaysTouchesBegan = YES; view = <UILayoutContainerView 0x7fd9a1415480>; target= <(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fd9a16003c0>)>>
通過log土全,interactivePopGestureRecognizer屬性其實是UIScreenEdgePanGestureRecognizer類,查看UIScreenEdgePanGestureRecognizer.h源文件会涎,繼承自UIPanGestureRecognizer裹匙,包含一個屬性edges,也就是所有邊緣末秃,從這個枚舉看出都是設置邊緣的概页,無法修改edges為全部
typedef NS_OPTIONS(NSUInteger, UIRectEdge) {
UIRectEdgeNone = 0,
UIRectEdgeTop = 1 << 0,
UIRectEdgeLeft = 1 << 1,
UIRectEdgeBottom = 1 << 2,
UIRectEdgeRight = 1 << 3,
UIRectEdgeAll = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight
} NS_ENUM_AVAILABLE_IOS(7_0);
所以,我們要做的是练慕,創(chuàng)建一個UIPanGestureRecognizer手勢惰匙,讓它的target和action執(zhí)行系統(tǒng)響應的方法,所以可以用runtime獲取系統(tǒng)手勢的target和action
unsigned int count = 0;
Ivar *var = class_copyIvarList([UIGestureRecognizer class], &count);
for (int i = 0; i < count; i++) {
Ivar _var = *(var + i);
NSLog(@"%s ------ %s",ivar_getName(_var),ivar_getTypeEncoding(_var));
}
接下來铃将,可以通過KVC獲取_targets了
NSMutableArray *targets = [self.navigationController.interactivePopGestureRecognizer valueForKeyPath:@"_targets"];
NSLog(@"%@",targets);
/*
(
"(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fdbf2e02110>)"
)
*/
_targets數(shù)組中就一個元素项鬼,雖然不知道什么類型,可以選擇用 id 接收劲阎。如果想繼續(xù)探究绘盟,那就打斷點看下控制臺,isa指向UIGestureRecognizerTarget私有類悯仙。
代碼
我們可以在自定義的NavigationController中添加以下代碼
@interface SSNavigationController ()<UIGestureRecognizerDelegate>
@end
@implementation SSNavigationController
- (void)viewDidLoad {
[super viewDidLoad];
[self initGlobalPan];
}
-(void)initGlobalPan
{
//取消系統(tǒng)自帶手勢
self.interactivePopGestureRecognizer.enabled = NO;
//獲取系統(tǒng)的手勢的target數(shù)組
NSMutableArray *_targets = [self.interactivePopGestureRecognizer valueForKeyPath:@"_targets"];
//獲取target
id target = [[_targets firstObject] valueForKeyPath:@"_target"];
//獲取action
SEL action = NSSelectorFromString(@"handleNavigationTransition:");
//創(chuàng)建一個與系統(tǒng)一樣的手勢 只把它的類改為UIPanGestureRecognizer
UIPanGestureRecognizer *popRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget: target action: action];
popRecognizer.delegate = self;
//添加到系統(tǒng)手勢作用的view上
UIView *gestureView = self.interactivePopGestureRecognizer.view;
[gestureView addGestureRecognizer:popRecognizer];
}
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
//當前控制器為根控制器龄毡,pop動畫正在執(zhí)行的時候不允許手勢
return self.viewControllers.count != 1 && ![[self valueForKeyPath:@"_isTransitioning"] boolValue];
}
@end