Wednesday, June 7, 2017

UIApplicationExitOnSuspend for Suspend not Background

Leave a Comment

I have an application that tends to stay awake in the background due to it playing music; however, on a rare occasion if the music stops between songs for longer than expected(can be relatively short amount of time) due to connectivity issues or the user mutes the music, the application will become suspended. I am aware of UIApplicationExitOnSuspend but unlike the description of it, this actually exits on entering background. I have done a fair amount of research, I am aware there are no system notifications for entering suspending state.

Is there anyway to identify on leaving suspended state that the app was suspended? Alternatively is there anyways to do something similar to UIApplicationExitOnSuspend except only when the application actually is suspended not just when it goes into the background?

2 Answers

Answers 1

You could try using the backgroundtimeremaining property on UIApplication, poll it with a timer on some interval, and should that value get close enough to zero - set a flag, or even a value in userDefaults, which you could then check and unset after coming back to the foreground?

The documentation reads:

This property contains the amount of time the app has to run in the background before it may be forcibly killed by the system. While the app is running in the foreground, the value in this property remains suitably large. If the app starts one or more long-running tasks using the beginBackgroundTask(expirationHandler:) method and then transitions to the background, the value of this property is adjusted to reflect the amount of time the app has left to run.

Answers 2

I ended up creating a small class to identify when the app has gone into a suspended state:

class SuspendedMonitor {   static let shared = SuspendedMonitor()    var delegate: SuspendedMonitorDelegate?    private let Interval = 10.0    private let MaxDelta = 2.0    private var _timestamp: Double    private var _timer: Timer?    private init() {     _timestamp = timeInMs()   }    public func start() {     _timestamp = timeInMs()      NotificationCenter.default.addObserver(       self,       selector: #selector(enterForeground),       name: NSNotification.Name.UIApplicationWillEnterForeground,       object: nil     )      NotificationCenter.default.addObserver(       self,       selector: #selector(enterBackground),       name: NSNotification.Name.UIApplicationDidEnterBackground,       object: nil     )   }    @objc func enterForeground() {     checkSync()     _timer?.invalidate()   }    @objc func enterBackground() {     _timestamp = timeInMs()     setupTimer()   }    @objc func incrementTime() {     _timestamp = _timestamp + (Interval * 1000)   }    private func setupTimer() {     _timer = Timer.scheduledTimer(       timeInterval: Interval,       target: self,       selector: #selector(incrementTime),       userInfo: nil,       repeats: true     )   }    private func checkSync() {     if timeInMs() - _timestamp > ((Interval + MaxDelta) * 1000) { appSuspended() }   }    private func appSuspended() {     delegate?.appDidSuspend(self)   }  }  protocol SuspendedMonitorDelegate: class {   func appDidSuspend(_ monitor: SuspendedMonitor) } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment