2

What is the prescribed method of figuring out a user's latitude and longitude from the complication?

I've tried instantiating a location manager inside the complication controller, and requesting the location, both using requestLocation, and startUpdatingLocation. Neither responds with an update.

I am using watchOS 4.0 and iOS 9.3.

Any help is greatly appreciated.

Will Powers
  • 155
  • 1
  • 6

2 Answers2

3

A few important points:

  1. Don't do any computation or async request in your Complication Controller, you will eat up your complication update budget for a day very quickly, plus OS will suspend the process after a few seconds.

  2. You can use Core Location in your Extension Delegate either in foreground (no restrictions) or in the background. If you want to use it in the background, you need to set UIBackgroundModes to location in your WatchKit Extension's Info.plist AND your location manager's allowBackgroundLocationUpdates property to true. Don't forget to set it to false when you don't need constant location updates. For instance, if you need to request the location once in the background, turn that property off once you receive the location fix.

  3. You can only update your complication so many times during the day (Apple doesn't publish the exact number). You can expect to be able to update it at least 4-6 times an hour, possibly more, but definitely not every minute. So you can forget about displaying any real-time data on your complication.

Eugr
  • 76
  • 2
  • Thank you. I now have my complication working, fetching data every half hour. I do have some concerns I'm not doing it properly. In order to update my location, I schedule a background app refresh event. I then call 'requestLocation', which doesn't do continuous updates. It just runs once. When that returns a location, I make a call with the lat/lon to apple's geocoder service. When that returns, I make a call to another endpoint using the lat/lon again. The thing is, in order to use Apple's geocoder service, I can't run NSURLSession in the background. (continued...) – Will Powers Oct 21 '18 at 01:22
  • So I don't do a BackgroundURLRefresh within the app refresh, as Apple prescribes. Instead, I grab a my shared data manager, and pass the background task to it from inside of the handleBackgroundTasks function. I then start the chain of calls with requestLocation. Once the chain has completed, I call [backgroundTask setTaskCompletedWithSnapshot:YES] to release control of the background. But this seems like the wrong way to do this. For one thing, I'm not sure about the persistence of the backgroundTask object in another class (which I hand over as nonatomic, strong). Any suggestions? – Will Powers Oct 21 '18 at 01:26
  • Well, it's not necessarily the wrong way, and from my experience data tasks inside background handlers work in a much more reliable and predictable fashion than background URL fetch sessions. However, you are still limited by 15 second wall clock time for all your background stuff, including fetching the location and both URL requests, so if you have a bad connection, your process may be killed in the middle of request and the request will never finish. – Eugr Oct 22 '18 at 14:56
  • I wouldn't worry about passing the reference to the background task as long as you dispose of that reference once you are done. – Eugr Oct 22 '18 at 15:03
  • I have a similar workflow, but I make a single URL request instead of two after receiving location, so I pass control to background URL session once I retrieve the location, so it works even with a bad connection. However, I would advice against doing it with chained requests, as background URL session will introduce artificial delay if you start chaining them (to prevent it from being used as a workaround to keep your app in the background). You will need to use your own server and consolidate all that work in a single request. – Eugr Oct 22 '18 at 15:03
1

The complication by itself is only a display item for the user interface. Any processing needed must be in the WKExtensionDelegate using the WKRefreshBackgroundTask for the processing. Read up on background modes as well.

Cobra
  • 369
  • 1
  • 6