zoukankan      html  css  js  c++  java
  • iOS事件拦截及应用

    1.概述

      我们知道事件的分发是由Application到Window再到各级View的,所以显然最安全可靠的拦截地方是Application。这里拦截事件后如果不手动往下分发,则进入hit-test View过程的机会都没有。

      UIApplication和UIWindow都有sendEvent:方法,用来分发Event。我们可以继承类,重新实现sendEvent:方法,这样就可以拦截下事件,完成一些特殊的处理,也可以利用runtime,将sendEvent:方法替换为我们自己的方法,添加一些我们自己的实现,然后再调用原来的消息流程。

    2.拦截方式

      1)利用runtime

    #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内调用即可

      2)继承UIApplication类,实现自己的sendEvent:

      应用场景如下,比如应用要求在非某个特定view的区域触摸时进行一项处理。

      我们当然可以在其余每一个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]));
        }
    }

    这样我们就实现了事件的预处理,抓住了源头,想做啥都可以。

      

  • 相关阅读:
    使用Python通过docker api控制docker容器
    windows 编译 google v8
    Kali下Metasploit自动连接postgresql
    更新Kali中的metasploit
    spring + mybatis 注解式事务不回滚的原因分析 @Transactional
    ListView中使用type需要注意的东西 java.lang.ArrayIndexOutOfBoundsException: length=2; index=2 addScrapView
    Missing artifact com.sun:tools:jar:1.5.0的解决方案
    0919-The Standard of Code Review
    重定向URL乱码问题
    hive学习_01
  • 原文地址:https://www.cnblogs.com/hlfme/p/4654966.html
Copyright © 2011-2022 走看看