55 lines
1.8 KiB
Swift
55 lines
1.8 KiB
Swift
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
|
|
import Foundation
|
|
import UIKit
|
|
|
|
class DevMenuTouchInterceptor {
|
|
static fileprivate let recognizer: DevMenuGestureRecognizer = DevMenuGestureRecognizer()
|
|
|
|
/**
|
|
Returns bool value whether the dev menu touch gestures are being intercepted.
|
|
*/
|
|
static var isInstalled: Bool = false {
|
|
willSet {
|
|
if isInstalled != newValue {
|
|
// Capture touch gesture from any window by swizzling default implementation from UIWindow.
|
|
swizzle()
|
|
|
|
// Make sure recognizer is enabled/disabled accordingly.
|
|
recognizer.isEnabled = newValue
|
|
}
|
|
}
|
|
}
|
|
|
|
static private func swizzle() {
|
|
DevMenuUtils.swizzle(
|
|
selector: #selector(getter: UIWindow.gestureRecognizers),
|
|
withSelector: #selector(getter: UIWindow.EXDevMenu_gestureRecognizers),
|
|
forClass: UIWindow.self
|
|
)
|
|
}
|
|
}
|
|
|
|
extension UIWindow {
|
|
@objc open var EXDevMenu_gestureRecognizers: [UIGestureRecognizer]? {
|
|
// Just for thread safety, someone may uninstall the interceptor in the meantime and we would fall into recursive loop.
|
|
if !DevMenuTouchInterceptor.isInstalled {
|
|
return self.gestureRecognizers
|
|
}
|
|
|
|
// Check for the case where singleton instance of gesture recognizer is not created yet or is attached to different window.
|
|
let recognizer = DevMenuTouchInterceptor.recognizer
|
|
if recognizer.view != self {
|
|
// Remove it from the window it's attached to.
|
|
recognizer.view?.removeGestureRecognizer(recognizer)
|
|
|
|
// Attach to this window.
|
|
self.addGestureRecognizer(recognizer)
|
|
}
|
|
|
|
// `EXDevMenu_gestureRecognizers` implementation has been swizzled with `gestureRecognizers`
|
|
// It might be confusing that we call it recursively, but we don't.
|
|
return self.EXDevMenu_gestureRecognizers
|
|
}
|
|
}
|