定向事件拦截,UIApplication的实例方法:
- (BOOL)sendAction:(SEL)action to:(nullable id)target from:(nullable id)sender forEvent:(nullable UIEvent *)event;
iOS中,继承于UIResponder的类能获得相应事件的能力,这类事件为UIControl Actions,基于Target/Action的方式分发。
根据事件传递链,事件由根节点UIApplication从Window进行向下分发寻找最合适的对象,根据响应者链条,从initial view向上寻找做出响应的对象。
继承于UIResponder且基于Target/Action方式的事件,都可以从上面的那个方法中获得,可以这么理解,UIApplication管理了这类事件,对这类事件进行分发和调度。
那么在这个方法中,我们能拿到一个事件所有的信息,能切入处理一些全局业务逻辑,例如事件统计,在某个条件下屏蔽某一类的响应等等。
像下面这样,我创建一个UIApplication的分类,重写此方法屏蔽所有的UIButton及其子类的响应,同时不对其它类造成影响:
- (BOOL)sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event {
if ([sender isKindOfClass:[UIButton class]]) {
NSLog(@"拦截btn");
return NO;
}
return YES;
}
这个时候会收到一个编译警告:Category is implementing a method which will also be implemented by its primary class,告知你不应该直接在分类中重写系统的方法,应该用子类去实现。一般来说我们确实不应该这么做,但这个方法的重写目前看是安全的,我们可以让编译器选择忽略这个警告:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"