iOS监测屏幕闲置时间

iOS监测屏幕闲置时间

即监测App是否被触摸,例如App在5分钟内没有被使用(没有接收都任何触摸操作),做相应的操作

我们知道事件的分发是由Application到Window再到各级View的,所以显然最安全可靠的拦截地方是Application。这里拦截事件后如果不手动往下分发,则进入hit-test View过程的机会都没有。
UIApplication和UIWindow都有sendEvent:方法,用来分发Event。我们可以继承类,重新实现sendEvent:方法,这样就可以拦截下事件,完成一些特殊的处理。
https://blog.csdn.net/sakulafly/article/details/18792631

在UIApplication中的介绍中,有这样的描述:

Most apps do not need to subclass UIApplication. Instead, use an app delegate to manage interactions between the system and the app.
If your app must handle incoming events before the system does—a very rare situation—you can implement a custom event or action dispatching mechanism. To do this, subclass UIApplication and override the sendEvent(_:) and/or the sendAction(_:to:from:for:) methods. For every event you intercept, dispatch it back to the system by calling [super sendEvent:event] after you handle the event. Intercepting events is only rarely required and you should avoid it if possible.

表示可以重写sendEvent(_:)方法,实现自定义的event或者action派发机制

所以可继承UIApplication,重写sendEvent(_:)方法

我参照iOS perform action after period of inactivity (no user interaction),写了个子类CFUIApplication继承UIApplication,重写了sendEvent(_:)方法,修改main.m,发现的确可以在发生任何触摸事件之后,拦截到

但是有一个问题,就是在某个登录页面,会发现整个页面都不响应事件了,UITextField的键盘弹不出来,UIButton也不响应事件了,这就很尴尬了…

之后跟踪了下,sendEvent(_:)方法的调用过程,竟然发现调用了gt3_swizzledMethod_3

iOS监测屏幕闲置时间_第1张图片

在我们的登录页面使用了极验,所以考虑是不是该方法被swizzled了

所以就考虑使用Category了,如下,参考dfox/uiapplication-method-swizzling.m:

#import "UIApplication+EventInterceptor.h"
#import <objc/runtime.h>
#import "EventLogger.h"

@implementation UIApplication (EventInterceptor)

+(void) load
{
    //Swap the implementations of our interceptor and the original sendEvent:
    Method oldMethod = class_getInstanceMethod(self, @selector(sendEvent:));
    Method newMethod = class_getInstanceMethod(self, @selector(interceptAndSendEvent:));
    method_exchangeImplementations(oldMethod, newMethod);
}

-(void) interceptAndSendEvent: (UIEvent *) event
{
    for (UITouch *touch in event.allTouches){
        if (touch.phase == UITouchPhaseBegan){
            [EventLogger logEvent:EVENT_LOGGER_TOUCHED forObject:touch.view];
        }
    }
    [self interceptAndSendEvent:event];
}

就OK了

Swift的实现可参考:

  • Detecting user inactivity in iOS application

UIWindow重写:

  • ios-runtime拦截touch事件,展示用户触摸效果

你可能感兴趣的:(iOS,基本)