我正在尝试为我使用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];
}
}
上面的代码适用于每次触摸,但只有在UIWindow的层次结构之上不存在视图时,swift等效项才有效吗?
有没有人知道如何检测应用程序中的每一次触摸?
答案 0 :(得分:14)
由于我的应用程序中有类似内容,我只是尝试修复它:
sendEvent
中覆盖UIWindow
- 无效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
。
答案 1 :(得分:0)
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
}
答案 2 :(得分:0)
@markiv答案就像一个咒语,有两个问题:
可以这样解决:
let kw = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
找到here
查看@matt的答案
AppDelegate-我收到此消息:
一个可以继承UIWindow的子类-找到了答案here。将此与IdlingWindow类结合使用。
消息消失了。
var customWindow: IdlingWindow?
var window: UIWindow? {
get {
customWindow = customWindow ?? IdlingWindow(frame: UIScreen.mainScreen().bounds)
return customWindow
}
set { }
}