How to know when the user has started an Apple Watch app? - ios

I would like to know when the user starts my Apple Watch app (started from menu or from complication). WKInterfaceController's documentation states that the didAppear method is called when the interface controller content is on screen.
In my simple example project I'm logging all calls to the didAppear method, and I see that it gets called also when the app is not visible on screen.
override func didAppear() {
super.didAppear()
log("didAppear") // Triggered when app not visible
}
My guess is that this has to do with snapshot refreshing, but is there any way to know when the user (not the system) has started my app?

Use applicationDidBecomeActive for this.
From Apple Developer Documentation:
WatchKit calls this method to let you know that your app transitioned from the inactive to the active state. Use this method to start any tasks that were paused or not yet started while the app was inactive.

Related

how to tell when the device screen is locked or unlocked in swift

Essentially I have a timer in my app and I need it to keep running if the phone or device gets locked while the timer is active. After a whole lot of searching I found that's not really possible, or well it is, but doing so could violate apple developer guidelines and could get the app removed from the store.
So I thought I would get a little clever and create a property in my AppDelegate of Int64 for "timerStartedAt" which is just a Date().millisecondsSince1970 (custom extension I have)...
extension Date {
var millisecondsSince1970: Int64 {
return Int64((self.timeIntervalSince1970 * 1000.0).rounded())
}
init(milliseconds: Int64) {
self = Date(timeIntervalSince1970: TimeInterval(milliseconds) / 1000)
}
}
Then in the "viewWillAppear" of my timer view controller I check that property and set the time has been running of now - that time. However, viewWillAppear doesn't get called when the screen is unlocked. It does get called if the user switches pages in the application, but not when the screen locks and then unlocks.
So I am trying to find a way to call a method in my view controller when the device gets unlocked. Is that even possible?
As the device is being locked, if your app was frontmost, then you'll get applicationWillResignActive(_:) in the app delegate, and the corresponding notification if you register for it.
As the device is being unlocked, if your app was frontmost, then it will be active and frontmost again and you'll get applicationDidBecomeActive in the app delegate, and the corresponding notification if you register for it.
(If your app was not frontmost, you have no way to detect that anything is happening, but that's okay because there is no "you" — the app is not running.)
That is sufficient to let you write a timer that "keeps counting" in the background by looking at the different between the time it started (or the time we deactivated) and the time when we are activated. So the timer effectively "runs" in the background.

Perform action when opening app for the second time

When I open the app it fires the events viewDidLoad and viewDidAppear form my View Controller but when I close it and run it again it does not call any of them.
Any idea?
You need to read up on application states. Here is a link I found online outlining the different states:
http://www.techrepublic.com/blog/software-engineer/understand-the-states-and-transitions-of-an-ios-app/
What you really want is to be notified when your app becomes active.
Probably the easiest way is to implement the function applicationDidBecomeActive() in your app delegate. That will be called when your app becomes active as the foreground app either on launch, or when it returns to the foreground as the active app.
Note that if you want that notification sent to some object other than the app delegate you can listen for the UIApplicationDidBecomeActive notification.

Updating App from Background

I have been writing an app that involves updating several values depending on the time the user is in - I update these values using viewDidAppear but unfortunately this function is not being called when the app is loaded again after being sent to the background.
Is there any way to prevent the app from being sent to the background? Or to force the app to open on a certain page after being opened from the background? Or is there a function that is like viewDidAppear, but is always whenever the app is loaded from the background?
Thanks!
Note:
I tried this:
func applicationDidBecomeActive() {
viewDidAppear(false)
}
inside the viewController class, but it didn't work.
You may be looking for applicationWillEnterForeground(application: UIApplication). This method has to be implemented in AppDelegate, not in a controller

Exit from a Watchkit app is handled by the Watchkit OS itself, I don't need to clear or reset screen?

OK, this is pretty basic but I've read the documentation over and over and want to be sure I've got this right. In plain language, my watchkit app will be shut down by some user interaction exiting the app that's external to my code, right? I don't need to clear or reset the screen with any kind of close procedure that sets it up for another run? I don't need to build an "Exit" or "Close app" routine, right? It's confusing because the documentation implies the app will deactivate once it's no longer on screen (presumably by a user action like swiping to another app) and that this will call the didDeactivate function. But the documentation also claims:
In iOS Simulator, WatchKit calls the didDeactivate method for the current
interface controller when you lock the simulator by selecting Hardware > Lock.
When you subsequently unlock the simulator, WatchKit calls that interface
controller’s willActivate method again. You can use this capability to debug
your activation and deactivation code.
But the simulator doesn't appear to deallocate memory or reset variables or reset my app in any way. It remains persistent on screen in the state at the time of the lock, and it comes back in that state when I unlock. What worries me is that if I've got this wrong, I have an app built for one run. But I don't see routines for shutdown, screen clearance, or any of the elements you'd expect in a conventional shutdown routine.
I agree that the documentation can be confusing. The easiest way to think about it is that willActivate is called whenever your interface controller is displayed/activated. Likewise, didDeactivate is called whenever it is hidden/deactivated. So, if you're flipping through pages of controllers, each will receive a willActivate when it shows up and a didDeactivate when it disappears. Similarly, if a controller is deactivated because the app is no longer visible (e.g. it was suspended), didDeactivate will be called. If the user then raises their wrist to resume the app, willActivate is called, because the interface controller is being displayed.
There is no promise about whether your WatchKit app will be suspended or terminated (it's up to the OS), so you have to consider both possibilities. Based on experience, I know that dropping your arm will call didDeactivate before suspending your app. If you then raise your wrist, the app will resume and call willActivate. In my testing, the app was simply suspended (not terminated) in this situation.
You're correct that there is no built-in method that is called when the app is terminated. However, iOS 8.2 added four notifications that can be used to monitor the app/extension's state:
NSExtensionHostDidBecomeActiveNotification
NSExtensionHostDidEnterBackgroundNotification
NSExtensionHostWillEnterForegroundNotification
NSExtensionHostWillResignActiveNotification

Can I figure out in iOS whether the app is resuming from standby or from multitasking

I'm currently working on a change request for our iPad app that requires that I handle the resuming of the app in two different ways depending on whether the app returned from multitasking (the user was active in another app or on the homescreen and came back to the app) and standby (the iPad was switched to standby either through the standby button on top or by closing the Smart Cover)
In both cases the following methods are called in my AppDelegate:
applicationWillResignActive followed by applicationDidEnterBackground when I hit the homebutton to get tot he home screen or close the Smart Cover
applicationWillEnterForeground and applicationDidBecomeActive when I come back.
As the same methods are called I am a bit lost on how to detect where I come from on resume. All four methods have a single parameter passing in the UIApplication. I looked at its interface, but didn't find any useful clues.
Is there a way to differentiate between resuming from multitasking or standby?
There is no public api method to define why application did become active

Resources