1.概述安全
咱們知道事件的分發是由Application到Window再到各級View的,因此顯然最安全可靠的攔截地方是Application。這裏攔截事件後若是不手動往下分發,則進入hit-test View過程的機會都沒有。app
UIApplication和UIWindow都有sendEvent:方法,用來分發Event。咱們能夠繼承類,從新實現sendEvent:方法,這樣就能夠攔截下事件,完成一些特殊的處理,也能夠利用runtime,將sendEvent:方法替換爲咱們本身的方法,添加一些咱們本身的實現,而後再調用原來的消息流程。函數
2.攔截方式post
1)利用runtimespa
#import "EventHookObject.h" #import <objc/objc.h> #import <objc/runtime.h> @implementation EventHookObject + (void)initialize { Method sendEvent = class_getInstanceMethod([UIApplication class], @selector(sendEvent:)); Method mySendEvent = class_getInstanceMethod([self class], @selector(mySendEvent:)); IMP sendEventIMP = method_getImplementation(sendEvent); class_addMethod([UIApplication class], @selector(sendEventOri:), sendEventIMP, method_getTypeEncoding(sendEvent)); IMP mySendEventIMP = method_getImplementation(mySendEvent); class_replaceMethod([UIApplication class], @selector(sendEvent:), mySendEventIMP, method_getTypeEncoding(sendEvent)); } /* * 截獲到UIApplication的sendEvent * 咱們能夠先處理完之後,再繼續調用正常處理流程 */ - (void)mySendEvent:(UIEvent*)event { //這裏能夠添加一些你想要的處理 [self performSelector:@selector(sendEventOri:) withObject:event]; }
而後就是在函數- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions內調用便可code
2)繼承UIApplication類,實現本身的sendEvent:orm
應用場景以下,好比應用要求在非某個特定view的區域觸摸時進行一項處理。blog
咱們固然能夠在其他每個view裏面增長代碼進行判斷,不過這樣比較累,容易漏掉一些地方,比較簡單的解決方案就是在繼承UIApplication類,實現本身的sendEvent:,在這個方法裏面初步過濾一下事件,是觸摸事件就發送Notification,而特定的view會註冊這個Notification,收到後判斷一下是否觸摸到了本身以外的區域。繼承
#import "EventApplication.h" NSString *const NotificationScreenTouch = @"NotificationScreenTouch"; @implementation EventApplication - (void)sendEvent:(UIEvent *)event { if (event.type == UIEventTypeTouches) { if ([[event.allTouches anyObject] phase] == UITouchPhaseBegan) { [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:NotificationScreenTouch object:nil userInfo:[NSDictionary dictionaryWithObject:event forKey:@"value"]]]; } } [super sendEvent:event]; } @end
在main.m文件中替換掉UIApplication的調用事件
#import <UIKit/UIKit.h> #import "AppDelegate.h" #import "EventApplication.h" int main(int argc, char *argv[]) { @autoreleasepool { //return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); return UIApplicationMain(argc, argv, NSStringFromClass([EventApplication class]), NSStringFromClass([AppDelegate class])); } }
這樣咱們就實現了事件的預處理,抓住了源頭,想作啥均可以。