iOS perform action after period of inactivity (no user interaction)

前端 未结 6 2019
慢半拍i
慢半拍i 2020-11-28 01:46

How can I add a timer to my iOS app that is based on user interaction (or lack thereof)? In other words, if there is no user interaction for 2 minutes, I want to have the ap

6条回答
  •  醉话见心
    2020-11-28 02:09

    Background [Swift Solution]

    There was a request to update this answer with Swift so I've added a snippet below.

    Do note that I have modified the specs somewhat for my own uses: I essentially want to do work if there are no UIEvents for 5 seconds. Any incoming touch UIEvent will cancel previous timers and restart with a new timer.

    Differences from Answer Above

    • Some changes from the accepted answer above: instead of setting up the first timer upon the first event, I set up my timer in init() immediately. Also my reset_idle_timer() will cancel the previous timer so only one timer will be running at any time.

    IMPORTANT: 2 Steps Before Building

    Thanks to a couple great answers on SO, I was able to adapt the code above as Swift code.

    • Follow this answer for a rundown on how to subclass UIApplication in Swift. Make sure you follow those steps for Swift or the snippet below won't compile. Since the linked answer described the steps so well, I will not repeat here. It should take you less than a minute to read and set it up properly.

    • I could not get NSTimer's cancelPreviousPerformRequestsWithTarget: to work, so I found this updated GCD solution which works great. Just drop that code into a separate .swift file and you are gtg (so you can call delay() and cancel_delay(), and use dispatch_cancelable_closure).

    IMHO, the code below is simple enough for anyone to understand. I apologise in advance for not answering any questions on this answer (a bit flooded with work atm).

    I just posted this answer to contribute back to SO what great information I've gotten out.

    Snippet

    import UIKit
    import Foundation
    
    private let g_secs = 5.0
    
    class MYApplication: UIApplication
    {
        var idle_timer : dispatch_cancelable_closure?
    
        override init()
        {
            super.init()
            reset_idle_timer()
        }
    
        override func sendEvent( event: UIEvent )
        {
            super.sendEvent( event )
    
            if let all_touches = event.allTouches() {
                if ( all_touches.count > 0 ) {
                    let phase = (all_touches.anyObject() as UITouch).phase
                    if phase == UITouchPhase.Began {
                        reset_idle_timer()
                    }
                }
            }
        }
    
        private func reset_idle_timer()
        {
            cancel_delay( idle_timer )
            idle_timer = delay( g_secs ) { self.idle_timer_exceeded() }
        }
    
        func idle_timer_exceeded()
        {
            println( "Ring ----------------------- Do some Idle Work!" )
            reset_idle_timer()
        }
    }
    

提交回复
热议问题