iOS事件攔截處理 – iPhone手機開發技術文章 iPhone軟體開發教學課程

前面分析瞭一通iOS事件的分發,主要介紹瞭事件如何找到處理的view,又是如何按照responder chain逐級傳遞的。這篇文章主要介紹iOS事件的攔截以及特殊處理。

我們知道事件的分發是由Application到Window再到各級View的,所以顯然最安全可靠的攔截地方是Application。這裡攔截事件後如果不手動往下分發,則進入hit-test View過程的機會都沒有。

UIApplication和UIWindow都有sendEvent:方法,用來分發Event。我們可以繼承類,重新實現sendEvent:方法,這樣就可以攔截下事件,完成一些特殊的處理。

比如:有一個iPad應用,要求在非某個特定view的區域觸摸時進行一項處理。

我們當然可以在其餘每一個view裡面增加代碼進行判斷,不過這樣比較累,容易漏掉一些地方;另外當UI需求變更時,維護的GG往往會栽進這個坑,顯然這不是一個好方法。

這裡比較簡單的解決方案就是在繼承UIApplication類,實現自己的sendEvent:,在這個方法裡面初步過濾一下事件,是觸摸事件就發送Notification,而特定的view會註冊這個Notification,收到後判斷一下是否觸摸到瞭自己之外的區域。

恩,還是上代碼吧,比較清楚一點:

1. 繼承UIApplication的DPApplication類

#import 

extern NSString *const notiScreenTouch;

@interface DPApplication : UIApplication

@end

#import "DPApplication.h"

NSString *const notiScreenTouch = @"notiScreenTouch";

@implementation DPApplication

- (void)sendEvent:(UIEvent *)event
{
    if (event.type == UIEventTypeTouches) {
        if ([[event.allTouches anyObject] phase] == UITouchPhaseBegan) {
            [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:notiScreenTouch object:nil userInfo:[NSDictionary dictionaryWithObject:event forKey:@"data"]]];
        }
    }
    [super sendEvent:event];
}

@end

2.要在main.m文件中替換掉UIApplication的調用

#import 

#import "AppDelegate.h"
#import "DPApplication.h"

int main(int argc, char *argv[])
{
    @autoreleasepool {
        //return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        return UIApplicationMain(argc, argv, NSStringFromClass([DPApplication class]), NSStringFromClass([AppDelegate class]));
    }
}

3. 這時已經實現瞭攔截消息,並在touchBegan的時候發送Notification,下面就是在view裡面註冊這個Notification並處理

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onScreenTouch:) name:notiScreenTouch object:nil];

- (void)onScreenTouch:(NSNotification *)notification
{
    UIEvent *event=[notification.userInfo objectForKey:@"data"];
    
    NSLog(@"touch screen!!!!!");
    CGPoint pt = [[[[event allTouches] allObjects] objectAtIndex:0] locationInView:self.button];
    NSLog(@"pt.x=%f, pt.y=%f", pt.x, pt.y);
}

這樣就實現瞭事件的預處理,固有的事件處理機制也沒有破壞,這個預處理是靜悄悄的進行的。當然,如果我需要把某些事件過濾掉,也隻需在DPApplication的sendEvent:方法裡面拋棄即可。

發佈留言