Swift - 使用计时器检测用户不活动,然后在 4 分钟后显示警报,以提示用户是否还在那里



我有一个基本的iPad应用程序,它由4个视图组成。在整个应用程序中,我希望能够检测用户不活动,然后在 4 分钟后显示警报,询问用户是否还在那里。

我找到了一些关于计时器和警报功能的有用资源。我已经尝试了这些教程,可以让计时器自己工作。但是,这是我第一次使用 Swift 进行开发,所以我想就将计时器连接到警报的最佳方式提供一些指导?我希望计时器运行 4 分钟,然后创建警报。

我还想知道放置这些元素代码的最佳位置在哪里,以便它们适用于我的所有 4 个视图。例如,是否有一个地方可以放置代码并重用它,而不是在 4 个视图中的每一个中重复它?

首先,您可以按照此处的说明设置计时器:https://blog.gaelfoppolo.com/detecting-user-inactivity-in-ios-application-684b0eeeef5b

然后,您可以执行以下操作来处理超时通知:

extension UIViewController {
func observeTimeout() {
NotificationCenter.default.addObserver(
self,
selector: #selector(handleTimeout),
name: .appTimeout,
object: nil)
}
@objc func handleTimeout() {
let alert = UIAlertController(title: "Timeout", message: "Oh no!", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
}))
present(alert, animated: true, completion: nil)
}
}

然后在每个视图控制器中执行此操作以注册超时:

class SomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
observeTimeout()
}
}

自从提出这个问题以来已经有一段时间了,但是,由于我遇到了同样的问题,因此我稍微更改了使用本指南提供的答案@rob-c:

在 Swift 5.5 和 iOS 15.1 上测试


1- 创建 UIApplication 的子类

import Foundation
import UIKit
class TimerApplication: UIApplication {
private var timeoutInSeconds: TimeInterval {
return 40.0
}
private var idleTimer: Timer?

override init() {
super.init()
resetIdleTimer()
}

private func resetIdleTimer() {
if let idleTimer = idleTimer {
idleTimer.invalidate()
}
idleTimer = Timer.scheduledTimer(timeInterval: timeoutInSeconds,
target: self,
selector: #selector(TimerApplication.timeHasExceeded),
userInfo: nil,
repeats: false
)
}
@objc private func timeHasExceeded() {
NotificationCenter.default.post(name: .appTimeout, object: nil)
}
override func sendEvent(_ event: UIEvent) {
super.sendEvent(event)
if idleTimer != nil {
self.resetIdleTimer()
}
if let touches = event.allTouches {
for touch in touches where touch.phase == UITouch.Phase.began {
self.resetIdleTimer()
}
}
}
}

2-添加通知名称

import Foundation
extension Notification.Name {
static let appTimeout = Notification.Name("appTimeout")
}

3-创建主.swift文件并添加此文件

import Foundation
import UIKit
/// NOTE: comment out @UIApplicationMain in AppDelegate
UIApplicationMain(
CommandLine.argc,
CommandLine.unsafeArgv,
NSStringFromClass(TimerApplication.self),
NSStringFromClass(AppDelegate.self)
)

4-从应用程序代表中删除@UIApplicationMain

5-为通知添加观察者

在适合您的案例的地方,在 AppDelegate 或任何视图控制器中添加观察者:

func addObservers() {
NotificationCenter.default.addObserver(self,
selector: #selector(idleTimeLimitReached(_:)),
name: .appTimeout,
object: nil)
}

@objc func idleTimeLimitReached(_ notification: Notification) {
print("***** IDLE Time called")

}

您可以在 AppDelegate 本身中运行计时器,并从 AppDelegate 中显示如下所示的警报

func showAlertFromAppDelegates(){
let alertVC = UIAlertController(title: "Oops" , message: "Presented Alert from AppDelegates", preferredStyle: UIAlertController.Style.alert)
let okAction = UIAlertAction(title: "Okay", style: UIAlertAction.Style.cancel) { (alert) in
}
alertVC.addAction(okAction)
var presentVC = self.window!.rootViewController
while let next = presentVC?.presentedViewController
{
presentVC = next
}
presentVC?.present(alertVC, animated: true, completion: nil)
}

编辑: 添加了与计时器相关的代码,当您想要启动非活动状态时调用 startTimer((,并在不活动结束时调用 stopTimer((

func startTimer()
{
let interval = 4*60
timer = Timer.scheduledTimer(timeInterval: TimeInterval(interval), target: self, selector: #selector(self.showAlertFromAppDelegates), userInfo: nil, repeats: true)
}
func stopTimer()
{
if let timer = timer
{
timer.invalidate()
}
timer = nil
}

最新更新