Situation:
Since our users have updated their iOS to 11 and/or WatchOS to 4, our iOS app doesn't seem to fire any scheduled timers when the app gets started by our WatchOS app. Maybe we are doing something wrong when starting our main app from the WatchOS app.
Context & code:
Our WatchOS app is a companion app that lets the user start/stop our iPhone app in the background by pressing a button. We do this by using:
func startMainApp() {
guard WCSession.default().isReachable == true else {
print("Watch is not reachable")
return
}
var data = [String : AnyObject]()
data[WatchActions.actionKey()] = NSNumber.init(value: WatchActions.startApp.rawValue as Int)
WCSession.default().sendMessage(data, replyHandler: { (result: [String : Any]) in
let resultNumber = result[WatchActions.resultKey()] as? NSNumber
let resultBool = resultNumber!.boolValue
if resultBool == true {
self.setModeActivated()
} else {
self.setModeActivationFailed()
}
}) { (error: Error) in
if (error as NSError).code != 7012 {
print("start app error: \(error.localizedDescription)")
self.setModeActivationFailed()
}
}
}
Then in our main app, we receive the message and start our base controller:
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
if let actionNumber : NSNumber = message[WatchActions.actionKey()] as? NSNumber {
if let watchAction : WatchActions = WatchActions(rawValue: actionNumber.intValue) {
switch(watchAction) {
case .isAppActive:
let result = BaseController.sharedInstance.sleepAndWakeUpController.isAwake()
replyHandler([WatchActions.resultKey() : NSNumber.init(value: result as Bool)])
return
case .startApp:
AudioController.sharedInstance().playActivatedSound()
let isRunningOnForeground = ApplicationStateHelper.isActive()
if isRunningOnForeground == false {
BaseController.sharedInstance.start(inBackground: true)
}
let result = true
replyHandler([WatchActions.resultKey() : NSNumber.init(value: result as Bool)])
DDLogInfo("[APPLE WATCH] [didReceiveMessage] [.startApp]")
return
}
}
}
replyHandler([WatchActions.resultKey() : NSNumber.init(value: false as Bool)])
return
}
Everything seems to work as before, we correctly get GPS locations, all our processes get started, however, Timer
objects that get started, don't fire.
This worked perfectly before on iOS 10, so I suspect this has something to do with iOS 11 background states that work differently. However, I cannot seem to find any documentation of this.
Extra info:
- On iOS 10, when we started our main app this way, the app got visible in the multitask view on the iPhone. Now on iOS 11, it isn't visible in the multitask view, however it does run on background. I successfully see local notifications that I schedule on the background, I can debug through the active code and when tapping the app icon, the app is immediately available.
- Our WatchOS app has the deployment target of 2.0
- Debugged via XCode with device connected, using Debug-->Attach to PID or Name-->Entered app name. Then start our app from the Apple Watch and debug.
- Reproducable on iOS 11.0.3 with WatchOS 4.0 on iPhone 6
Questions: What is the best way to start our main app from the watch app? Has something changed in iOS 11/WatchOS 4 regarding to background states? Can I find documentation of this? Could this be an iOS bug?