iOS用户点击屏幕事件抓取

引言

在开发当中,有各种各样的需求,很大部分的内容都是可以完成的,主观因素在于你连试过没没试过,就说做不了,证明一点就是懒,懒是程序猿的大忌。

莫懒

问题

产品提了一个新的需求
在iOSApp中,如果用户不操作界面的情况有超过2min,那么直接退出登录,断开跟硬件的连接,

分析

乍一听,感觉需求挺简单的,猜想:能做就是监听、重写touch方法

第一种监听的猜想

等我去做的时候,我发现OC有KVO监听属性的,那么怎么去监听方法是否被调用了呐? 我自己发现并没有,这个问题pass掉了 (如果有方法的童鞋,可以在评论中指点一下,不胜感激)

第二种重写touch事情的关键方法的猜想

这就涉及到事件产生、事件分发、事件响应(响应链)这个过程,
如果对响应链有所了解的话,找到你的事件分发的底层类,重写它分发的方法sendEvent(_:),你就能拿到响应的事件,在UIWindos、UIApplication都有这个方法,我们能重写的也只有UIWindows。

继续猜想,如果我在UIWindos中重写了sendEvent(:)这个方法,势必打破正常响应的过程,如果我知道sendEvent(:)里面的所有内容,我可以重新写一下它的源代码,然后添加一些自己的方法,主要因素是我不知道这个方法中的源代码,所以重写这个情况又被pass掉了

那么既不影响原有代码,又能添加一些自己的代码的方式有没有?

  • 有,runtime的黑魔法,互换一下UIApplication的sendEvent(_:)、自己创建的MysendEvent(_:)方法
  • 当系统调用sendEvent(_:)的时候会调用MysendEvent(_:)方法,同样调用MysendEvent(_:)方法会调用sendEvent(_:)
  • 所以只要在MysendEvent(_:)方法中添加自己的代码、最后在调用一下MysendEvent(_:)方法
    大功告成!
extension UIApplication {

    func changeMethod(_ object: AnyClass) -> () {
        
        let originalSelector = #selector(sendEvent(_:))
        let swizzledSelector = #selector(MysendEvent(_:))
        
        let originalMethod = class_getInstanceMethod(object, originalSelector)
        let swizzledMethod = class_getInstanceMethod(object, swizzledSelector)
        
        let didAddMethod: Bool = class_addMethod(object, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!))
        if didAddMethod {
            class_replaceMethod(object, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
        } else {
            method_exchangeImplementations(originalMethod!, swizzledMethod!)
        }
    }
    
    @objc func MysendEvent(_ event: UIEvent){
        
        //App的点击事件
        print("The user is active")
        MysendEvent(event)
        
    }
}

以上, 全局的去监听整个屏幕的点击事件

你可能感兴趣的:(iOS用户点击屏幕事件抓取)