美文网首页
fix third party keyboard crash (

fix third party keyboard crash (

作者: tom__zhu | 来源:发表于2023-08-15 14:20 被阅读0次

Overview
crash stack

#0 at 0x1d910a3a4

Thread 0 Crashed
0   libsystem_kernel.dylib  nil
1   libsystem_kernel.dylib  nil
2   libsystem_c.dylib   _os_crash_msg
3   UIKitCore   _UIResponderForwarderWantsForwardingFromResponder
4   UIKitCore   __forwardTouchMethod_block_invoke
5   CoreFoundation  __NSSET_IS_CALLING_OUT_TO_A_BLOCK__
6   CoreFoundation  -[__NSSetM enumerateObjectsWithOptions:usingBlock:]
7   UIKitCore   forwardTouchMethod
8   UIKitCore   -[UIWindow _sendTouchesForEvent:]
9   UIKitCore   -[UIWindow sendEvent:]
10  UIKitCore   -[UIApplication sendEvent:]
11  Eax-AppStore    EaxApplication.sendEvent(UIEvent)(Application.swift:16)
11  Eax-AppStore    @objc EaxApplication.sendEvent(UIEvent)(<compiler-generated>:14)
12  UIKitCore   __dispatchPreprocessedEventFromEventQueue
13  UIKitCore   __processEventQueue
14  UIKitCore   updateCycleEntry
15  UIKitCore   _UIUpdateSequenceRun
16  UIKitCore   schedulerStepScheduledMainSection
17  UIKitCore   runloopSourceCallback
18  CoreFoundation  __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
19  CoreFoundation  __CFRunLoopDoSource0
20  CoreFoundation  __CFRunLoopDoSources0
21  CoreFoundation  __CFRunLoopRun
22  CoreFoundation  CFRunLoopRunSpecific
23  GraphicsServices    GSEventRunModal
24  UIKitCore   -[UIApplication _run]
25  UIKitCore   UIApplicationMain
26  Eax-AppStore    main(main.swift:11)
27  unknown nil

scenario: page that contains keyboard
os version: 16.5.1
[[Application.swift:16 EaxApplication.sendEvent(UIEvent)]]



Clue

System keyboard: no crash

Third party keyboard: crash

  1. For iOS >= 9 third party keyboard will visible on UIRemoteKeyboardWindow window (UIRemoteKeyboardWindow is above all others window)
  1. touch event is sent to **UIRemoteKeyboardWindow **when third party keyboard just raise. Crash will happen when (multiple?) event sent to UIRemoteKeyboardWindow.

  2. After keyboard raised, touch event is sent to **UIRemoteKeyboardWindow **without crash

Recap: Crash happen only when third party keyboard receive (multiple?) event when it is about raise.

Suspect

UIRemoteKeyboardWindowreceive event when keyboard is about raise

Solution

  1. Block **UIRemoteKeyboardWindow **event chain
class EaxApplication: UIApplication {
    override func sendEvent(_ event: UIEvent) {
        if EaxABTestKey.shared.ENABLE_KEYBOARD_PROTECTION.isB() {
            guard canResponseToEvent(event) else { return }
        }
        sendNotificationToTTIModuleWhenFirstTouchIsFired(event)
        super.sendEvent(event)
    }
     
    override func sendEvent(_ event: UIEvent) {
        if EaxABTestKey.shared.ENABLE_KEYBOARD_PROTECTION.isB() {
            guard canResponseToEvent(event) else { return }
        }
        sendNotificationToTTIModuleWhenFirstTouchIsFired(event)
        super.sendEvent(event)
    }
     
    private func sendNotificationToTTIModuleWhenFirstTouchIsFired(_ event: UIEvent) {
        guard TTILogCore.defaultCenter.activated, event.type == .touches else { return }
        TTILogCenter.submitLog()
    }
     
    func canResponseToEvent(_ event: UIEvent) -> Bool {
        if UIDevice.current.systemVersion == "16.5.1" {
            if event.type == .touches {
                let allTouches: [UITouch] = Array(event.allTouches ?? [])
                for touch in allTouches {
                    let windowName = String(describing: touch.window.self)
                    if windowName.contains("UIRemoteKeyboardWindow") {
                        guard canResponseToWindow(touch.window) else { return false }
                    }
                }
            }
        }
         self.lastResponseDate = Date()
         return true
    }
     
    // Block UIRemoteKeyboardWindow event chain
    func canResponseToWindow(_ window: UIWindow?) -> Bool {
        guard Date().timeIntervalSince(lastResponseDate) >= timerInterval else {
            return false
        }
        return true
    }
}

  1. Block with timer interval for UIRemoteKeyboardWindow
class EaxApplication: UIApplication {
    override func sendEvent(_ event: UIEvent) {
        if EaxABTestKey.shared.ENABLE_KEYBOARD_PROTECTION.isB() {
            guard canResponseToEvent(event) else { return }
        }
        sendNotificationToTTIModuleWhenFirstTouchIsFired(event)
        super.sendEvent(event)
    }
     
    override func sendEvent(_ event: UIEvent) {
        if EaxABTestKey.shared.ENABLE_KEYBOARD_PROTECTION.isB() {
            guard canResponseToEvent(event) else { return }
        }
        sendNotificationToTTIModuleWhenFirstTouchIsFired(event)
        super.sendEvent(event)
    }
     
    private func sendNotificationToTTIModuleWhenFirstTouchIsFired(_ event: UIEvent) {
        guard TTILogCore.defaultCenter.activated, event.type == .touches else { return }
        TTILogCenter.submitLog()
    }
     
    func canResponseToEvent(_ event: UIEvent) -> Bool {
        if UIDevice.current.systemVersion == "16.5.1" {
            if event.type == .touches {
                let allTouches: [UITouch] = Array(event.allTouches ?? [])
                for touch in allTouches {
                    let windowName = String(describing: touch.window.self)
                    if windowName.contains("UIRemoteKeyboardWindow") {
                        guard canResponseToWindow(touch.window) else { return false }
                    }
                }
            }
        }
         self.lastResponseDate = Date()
         return true
    }
     
    // Block with timer interval for UIRemoteKeyboardWindow
    func canResponseToWindow(_ window: UIWindow?) -> Bool {
        if let currentWindow = currentWindow,
           currentWindow == window {
            return true
        } else {
            // key point: block event for UIRemoteKeyboardWindow for a period time
            currentWindow = window
            guard Date().timeIntervalSince(lastResponseDate) >= timerInterval else {
                return false
            }
            return true
        }
    }
     
}

UIRemoteKeyboardWindow Response Arear


When a new event is ready, we should check does this event belongs to UIRemoteKeyboardWindow and time interval is too shot to response.

Increase the time interval for different UIRemoteKeyboardWindow instance calls

Involved link

相关文章

网友评论

      本文标题:fix third party keyboard crash (

      本文链接:https://www.haomeiwen.com/subject/neyhmdtx.html