如何跨 SwiftUI 应用程序跟踪所有触摸
Posted
技术标签:
【中文标题】如何跨 SwiftUI 应用程序跟踪所有触摸【英文标题】:How to track all touches across SwiftUI app 【发布时间】:2020-09-16 20:25:50 【问题描述】:我正在尝试在 SwiftUI 应用中实现锁屏。
我需要跟踪每个事件以重新启动锁定计时器。
在 UIKit 应用程序中,我使用了这种方法 - 覆盖 UIApplication,它允许了解整个应用程序中的任何事件:
override func sendEvent(_ event: UIEvent)
super.sendEvent(event)
switch event.type
case .touches:
// Post Notification or Delegate here
default:
break
但在 SwiftUI 中不再支持它。 我尝试添加
.onTapGesture
到根 ContentView,但它没有按预期工作。
有什么办法可以避免添加
.onTapGesture
应用中的每一个视图?
【问题讨论】:
你可以看到这个答案:***.com/a/60010955/8697793 - 你可以调用你的自定义函数而不是 endEditing。 是的,这是一个很好的答案,但是没有 Scenedelegate 和 Window 的 ios 14 存在一些问题 【参考方案1】:这是一个可能的解决方案:
@main
struct TestApp: App
var body: some Scene
WindowGroup
ContentView()
.onAppear(perform: UIApplication.shared.addTapGestureRecognizer)
extension UIApplication
func addTapGestureRecognizer()
guard let window = windows.first else return
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapAction))
tapGesture.requiresExclusiveTouchType = false
tapGesture.cancelsTouchesInView = false
tapGesture.delegate = self
window.addGestureRecognizer(tapGesture)
@objc func tapAction(_ sender: UITapGestureRecognizer)
print("tapped")
extension UIApplication: UIGestureRecognizerDelegate
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool
return true // set to `false` if you don't want to detect tap during other gestures
【讨论】:
我在使用此代码时出现此错误'windows' was deprecated in iOS 15.0: Use UIWindowScene.windows on a relevant window scene instead
@RolandLariotte 应该是警告而不是错误。你可以用这个得到windows.first
的等价物。 connectedScenes.compactMap $0 as? UIWindowScene .flatMap $0.windows .first $0.isKeyWindow
您将在 SO 上看到的其他答案将包括对 .activationState == foregroundActive
的检查,但对于此特定实现,您应该将其关闭。【参考方案2】:
基于pawello2222's solution,我添加了 UIPanGestureRecognizer 以便在滚动或滑动应用时也能够识别。还添加了一个通知观察者,以便在从键盘输入文本时进行识别。解决方案如下所示:
@main
struct YourApp: App
var body: some Scene
WindowGroup
ContentView()
.onAppear
// Interaction recognizer implementation
UIApplication.shared.addInteractionRecognizer()
extension UIApplication
func addInteractionRecognizer()
// Notification observer to track text changes from keyboard
NotificationCenter.default.addObserver(self, selector: #selector(didInteractWithApp), name: UITextField.textDidChangeNotification, object: nil)
guard let window = windows.first else return
// Gestures recognizers to track
let gestureRecognizers = [
UITapGestureRecognizer(target: self, action: #selector(didInteractWithApp)),
UIPanGestureRecognizer(target: self, action: #selector(didInteractWithApp))
]
gestureRecognizers.forEach
$0.requiresExclusiveTouchType = false
$0.cancelsTouchesInView = false
$0.delegate = self
window.addGestureRecognizer($0)
@objc func didInteractWithKeyboard()
// Restart the lock timer
@objc func didInteractWithApp(_ sender: UIGestureRecognizer)
// Optional: Validate UIPanGestureRecognizer has ended, cancelled or failed, to prevent overloading for restarting timer. Remove if not needed
let allowedStates: [UIGestureRecognizer.State] = [.ended, .cancelled, .failed]
if sender as? UIPanGestureRecognizer != nil, !allowedStates.contains(sender.state)
return
// Restart the lock timer
extension UIApplication: UIGestureRecognizerDelegate
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool
// Set to true to recognize gestures specified above while allowing user interact with other gestures in the app and not to block them with them
return true
【讨论】:
以上是关于如何跨 SwiftUI 应用程序跟踪所有触摸的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 中如何获取任意视图触摸位置(全局或局部)的坐标
SwiftUI 中如何获取任意视图触摸位置(全局或局部)的坐标
如何在 Swift UIKit Map 组件中处理 SwiftUI 中的触摸手势?