【问题标题】:Calling UIApplication subclass method to start scheduledTimer调用 UIApplication 子类方法启动 scheduleTimer
【发布时间】:2020-01-02 21:28:54
【问题描述】:

我正在使用 Xcode 9.2/iOS 10 和 Swift 来检测用户在 iOS 应用程序中的不活动,使用基于来自 https://blog.gaelfoppolo.com/detecting-user-inactivity-in-ios-application-684b0eeeef5b 的优秀教程示例的信息我所做的增强是在调用 viewDidLoad 时启动计时器并添加贪睡applicationDidTimeout 中的函数。在编译时,会显示以下错误消息:“Instance member 'snoozeTimer' cannot be used on type 'TimerApplication';您的意思是改用此类型的值吗?”

applicationDidTimeout 将使用 snoozeTimer 来控制是否需要另一个计时器警报,具体取决于要添加到方法中的附加逻辑。

调用 startTimer 和 snoozeTimer 的正确方法是什么?

代码清单如下所示:

main.swift

UIApplicationMain(
   CommandLine.argc,
   UnsafeMutableRawPointer(CommandLine.unsafeArgv)
      .bindMemory(
         to: UnsafeMutablePointer<Int8>.self,
         capacity: Int(CommandLine.argc)),
   NSStringFromClass(TimerApplication.self),
   NSStringFromClass(AppDelegate.self)
)

AppDelegate.swift

import UIKit

import Foundation

extension Notification.Name {

    static let appTimeout = Notification.Name("appTimeout")

}

//@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

   var window: UIWindow?
   var backgroundTaskRunCount : Int = 0


   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
      // Override point for customization after application launch.

      NotificationCenter.default.addObserver(self,
                                             selector: #selector(AppDelegate.applicationDidTimeout(notification:)),
                                             name: .appTimeout,
                                             object: nil
      )


      return true
   }

.   //other func
 .
  .

@objc func applicationDidTimeout(notification: NSNotification) {
      backgroundTaskRunCount = backgroundTaskRunCount + 1

      print("application did timeout, perform actions. Count=", backgroundTaskRunCount)

      TimerApplication.snoozeTimer()
   }
}

TimerApplication.swift

import UIKit

class TimerApplication: UIApplication {

    private var wakeupInSeconds: TimeInterval {
        // 2 minutes for for timer to fire first time
        return 2 * 60
    }

    private let snoozeInSeconds: TimeInterval = 5

    // the timeout in seconds, after which should perform custom actions
    // such as disconnecting the user
    private var timeoutInSeconds: TimeInterval = 120

   private var idleTimer: Timer?

   // resent the timer because there was user interaction
   private func resetIdleTimer() {
      if timeoutInSeconds > 0 {
         if let idleTimer = idleTimer {
            idleTimer.invalidate()
         }

         idleTimer = Timer.scheduledTimer(timeInterval: timeoutInSeconds,
                                       target: self,
                                       selector: #selector(TimerApplication.timeHasExceeded),
                                       userInfo: nil,
                                       repeats: false
         )
      } else {
        stopTimer()
      }
   }

   // if the timer reaches the limit as defined in timeoutInSeconds, post this notification
   @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 == UITouchPhase.began {
            self.resetIdleTimer()
         }
      }
   }

    func startTimer() {
       self.timeoutInSeconds = wakeupInSeconds
       self.resetIdleTimer()
    }

    func stopTimer() {
        if let idleTimer = idleTimer {
            idleTimer.invalidate()
        }
    }

    func snoozeTimer() {
        self.timeoutInSeconds = snoozeInSeconds
    }
}

ViewController.swift

import UIKit

class ViewController: UIViewController {

   override func viewDidLoad() {
      super.viewDidLoad()
      // Do any additional setup after loading the view, typically from a nib.

    TimerApplication.startTimer()

   }

   override func didReceiveMemoryWarning() {
      super.didReceiveMemoryWarning()
      // Dispose of any resources that can be recreated.
   }


}

【问题讨论】:

  • 解决了吗?有同样的问题..任何帮助将不胜感激。!

标签: ios swift nstimer uiapplicationdelegate uiapplication


【解决方案1】:

您想使用TimerApplication.shared.snoozeTimer() 而不是TimerApplication.snoozeTimer(),因为snoozeTimer() 是一个实例方法,而不是类或静态方法。

您应该验证TimerApplication.shared 是否返回了您所期望的TimerApplication 的实例,因为我从未像这样子类化系统单例。如果这不起作用,您将需要一种方法来获取对所需 TimerApplication 实例的引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    • 2011-10-24
    • 2020-09-25
    • 1970-01-01
    • 2018-01-22
    • 1970-01-01
    相关资源
    最近更新 更多