业务需求:在选中某一Tab后,为其添加单击和双击事件(注意单击双击事件必须需独立,不能同时触发)
方案构思:
方案一:利用图层分析工具和KVC在
UITabBarItem
上添加自定义View,然后在View分别添加单击和双击手势
因为App原本使用的UITabBar
,而UITabBarItem
继承NSObject
,因此必须通过图层分析工具获取UITabBarItem里面的UI对象的类名,然后用runtime和KVC添加或修改属性。但稍加思考后,放弃了这种方案,原因有二:第一、可能用到苹果私有API,审核被拒。第二、每一个版本的UITabBarItem的UI对象都可能有所改变,至少在iOS8,13,15这几个版本UITabBarItem
的UI图层都略有改变。这样一来封装的代码非常麻烦,而且对于未来也iOS系统版本也有变数。方案二:直接在
UITabBar
上添加视图
这种方案的确比方案一稳定,但从代码封装角度来说,非常丑陋。方案三:在
UITabBarControllerDelegate
的- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
中添加通知事件,利用触发的时间间隔来区分单击和双击事件
通过研究发现,不论是在视图上添加手势还是利用时间间隔触发通知都有一个问题,就是双击事件事件没法脱离单击独立出现(因为第一次点击你是没法区分单双击的)
这里涉及一个技巧,就是单击事件需要延迟执行,如果双击事件触发了,则将处于延迟等待的单击事件取消掉。代码如下
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
///第二个item是你要处理单双击的情况
///tapTimestamp用于记录上一次点击的时间戳。
///doubleTapInterval是一个静态常量(我设置的为0.3)
NSUInteger index = [tabBarController.viewControllers indexOfObject:viewController];
if (index == 1 && tabBarController.selectedIndex == 1) {
NSTimeInterval timestamp = CFAbsoluteTimeGetCurrent();
if (timestamp - self.tapTimestamp < doubleTapInterval) {
[self postDoubleTapNotification];
}else {
[self performSelector:@selector(postSingleTapNotification) afterDelay:doubleTapInterval];
}
self.tapTimestamp = timestamp;
return NO;
}
return YES;
}
- (void)postSingleTapNotification {
[NotiCenter postNotificationName:LSTabBarSingleTapNotification object:nil];
}
- (void)postDoubleTapNotification {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(postSingleTapNotification) object:nil];
[NotiCenter postNotificationName:LSTabBarDoubleTapNotification object:nil];
}