如何检测 Swift 2 中的所有触摸
Posted
技术标签:
【中文标题】如何检测 Swift 2 中的所有触摸【英文标题】:How to detect all touches in Swift 2 【发布时间】:2015-07-26 23:22:05 【问题描述】:我正在尝试为我正在使用 Swift 2 开发的应用程序创建超时功能,但在 swift 2 中,您可以将此代码放在应用程序委托中,它可以工作,但它没有检测到任何键盘按下、按钮按下,文本字段印刷机等:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
super.touchesBegan(touches, withEvent: event);
let allTouches = event!.allTouches();
if(allTouches?.count > 0)
let phase = (allTouches!.first as UITouch!).phase;
if(phase == UITouchPhase.Began || phase == UITouchPhase.Ended)
//Stuff
timeoutModel.actionPerformed();
在 swift 2 之前,我能够拥有 AppDelegate 子类 UIApplication 并覆盖 sendEvent: 如下所示:
-(void)sendEvent:(UIEvent *)event
[super sendEvent:event];
// Only want to reset the timer on a Began touch or an Ended touch, to reduce the number of timer resets.
NSSet *allTouches = [event allTouches];
if ([allTouches count] > 0)
// allTouches count only ever seems to be 1, so anyObject works here.
UITouchPhase phase = ((UITouch *)[allTouches anyObject]).phase;
if (phase == UITouchPhaseBegan || phase == UITouchPhaseEnded)
[[InactivityModel instance] actionPerformed];
上面的代码适用于每次触摸,但 swift 等效代码仅在 UIWindow 的层次结构之上不存在视图时才有效?
有谁知道检测应用程序中每一次触摸的方法吗?
【问题讨论】:
它与 ios 9 而不是 Swift 2 有关。我在我的自定义UIWindow
中有类似的解决方案,它也停止工作。可能是因为新的 iOS 9 拆分应用程序视图等。所以他们重做了它以支持这些新功能 - 两个打开的应用程序、键盘......不是 100% 确定,只是大声思考......
【参考方案1】:
由于我的应用程序中有类似的东西,我只是尝试修复它:
在UIWindow
中覆盖sendEvent
- 不起作用
在委托中覆盖 sendEvent
- 不起作用
所以唯一的方法是提供自定义UIApplication
子类。到目前为止,我的代码(适用于 iOS 9)是:
@objc(MyApplication) class MyApplication: UIApplication
override func sendEvent(event: UIEvent)
//
// Ignore .Motion and .RemoteControl event
// simply everything else then .Touches
//
if event.type != .Touches
super.sendEvent(event)
return
//
// .Touches only
//
var restartTimer = true
if let touches = event.allTouches()
//
// At least one touch in progress?
// Do not restart auto lock timer, just invalidate it
//
for touch in touches.enumerate()
if touch.element.phase != .Cancelled && touch.element.phase != .Ended
restartTimer = false
break
if restartTimer
// Touches ended || cancelled, restart auto lock timer
print("Restart auto lock timer")
else
// Touch in progress - !ended, !cancelled, just invalidate it
print("Invalidate auto lock timer")
super.sendEvent(event)
为什么会有@objc(MyApplication)
。那是因为 Swift 对名称的处理方式与 Objective-C 不同,它只是说 - 我在 Objective-C 中的类名是 MyApplication
。
要使其正常工作,请打开您的 info.plist 并使用 Principal class 键和 MyApplication
值添加行(MyApplication
是 @objc(...)
内部的内容,而不是您的 Swift 类名称)。原始密钥是NSPrincipalClass
。
【讨论】:
注意一件事 - 这不会捕获外部键盘事件。如果你有 BT 键盘......只是屏幕/软件之一。 感谢您的提醒。我正在构建的这个应用程序需要输入外部配件,所以我必须研究一下。 别忘了在顶部导入 UIKit。这太棒了,正是我需要的。 你在 appdelegate 中实现了什么?你能分享你的整个代码吗?【参考方案2】:UIWindow
也有一个可以覆盖的sendEvent
方法。这将允许您跟踪自上次触摸屏幕以来的时间。斯威夫特 4:
class IdlingWindow: UIWindow
/// Tracks the last time this window was interacted with
var lastInteraction = Date.distantPast
override func sendEvent(_ event: UIEvent)
super.sendEvent(event)
lastInteraction = Date()
如果您使用的是故事板,您可以在didFinishLaunchingWithOptions
中加载它:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate
var window: IdlingWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
window = IdlingWindow(frame: UIScreen.main.bounds)
window?.rootViewController = UIStoryboard.init(name: "Main", bundle: nil).instantiateInitialViewController()
window?.makeKeyAndVisible()
return true
:
extension UIApplication
/// Conveniently gets the last interaction time
var lastInteraction: Date
return (keyWindow as? IdlingWindow)?.lastInteraction ?? .distantPast
现在在您的应用程序的其他地方,您可以像这样检查不活动:
if UIApplication.shared.lastInteraction.timeIntervalSinceNow < -2
// the window has been idle over 2 seconds
【讨论】:
不错的解决方案,但不幸的是:“'keyWindow' 在 iOS 13.0 中已弃用:不应用于支持多个场景的应用程序,因为它会在所有连接的场景中返回一个关键窗口”【参考方案3】:@markiv 的回答就像一个魅力,有两个问题:
-
键窗口
“'keyWindow' 在 iOS 13.0 中已被弃用:不应用于支持多个场景的应用程序,因为它会在所有连接的场景中返回一个关键窗口”
可以这样解决:
let kw = UIApplication.shared.windows.filter $0.isKeyWindow.first
找到here
查看@matt 的回答
AppDelegate - 我收到这条消息:
如果要使用主故事板文件,应用代理必须实现 window 属性可以继承 UIWindow - 找到答案here。将此与 IdlingWindow 类结合使用。
消息消失了。
var customWindow: IdlingWindow?
var window: UIWindow?
get
customWindow = customWindow ?? IdlingWindow(frame: UIScreen.mainScreen().bounds)
return customWindow
set
【讨论】:
以上是关于如何检测 Swift 2 中的所有触摸的主要内容,如果未能解决你的问题,请参考以下文章
在 swift 中,如何在 AVPlayerViewController 中播放视频时检测触摸