It appears that if I'm in the detail screen that I wish to unwind or pop from, all that has to be done is self.pop() or self.popToRootController().
I was looking for a method with the word "segue" in it, which is why I never found it. Thanks
Post
Replies
Boosts
Views
Activity
After much testing with passcode set/not set on various watches, I've determined that if there is no passcode set on the watch, the app updates the complications when on the charger. If the passcode is set then I get the "operation not permitted" error. Perhaps the temp files are created with complete file protection and as such are not allowed when the watch is locked.
So the issue was not having the watch on the charger but rather that the device was locked. Furthermore, my app is no longer dead when I take the watch off the charger in the morning.
After much testing on both WatchOS 6 & 7 here's what I've determined:
WatchOS 7 appears to have a better scheduling algorithm than WatchOS 6. Can't prove it though.
If my app has died and WatchOS starts it, although the scheduling of the background refresh still happens, the URLSessionDownloadDelegate's urlSession(_ downloadTask:didFinishDownloadingTo:) method is NOT called until the user either taps on one of my complications or starts the app from the home screen.
The times which I've observed skips in refresh, and my complication now says it's been over 15 minutes long is because a network error such as a timeout has occurred.
It appears that keeping a reference to the latest URLSession is worth doing, just ensure that you remove the reference when it has completed successfully or otherwise.
Using earliestBeginDate had a detrimental effect on my app. It would keep getting terminated by the system as soon as I resumed the first URLSession.
Although it is stated in the documentation that the OS will retry the request if a network error has occurred, I can't determine if that's true since I don't know how many times it actually retried.
I'm extremely embarrassed, but I finally figured out why Xcode 12's debugger was not starting and attaching to my WatchOS app. It was because I had set the scheme for my WatchOS app to not start automatically, and to wait until it was manually run.
I had this setting in Xcode 11 a long time ago, but for the simulator it never really worked, it would just always automatically launch the app, so I forgot all about it.
So with the exception that on the WatchOS 7 simulator the automatic "waiting to attach to app" still doesn't work, everything else is fine.
The issue must be uniquely related to my WatchOS app. Xcode 12 works fine with sample programs. For now I will debug by starting the WatchOS app manually and attaching to it. The shortcoming of this strategy is that all the debug statements no longer go to the Xcode console but rather to the OS X console's WatchOS simulator. It's the best I can do at the moment.
Thanks
I'm also having this issue with Xcode 12 (12A7209), when attempting to debug a WatchOS app on the simulator. Debugging an iPhone app works fine, and so does attaching to a running WatchOS app.
I take it this issue has not yet been resolved?
@developer555,
I also just added earliestBeginDate and the willBeginDelayedRequest delegate method, calling the completionHandler with .continueLoading. Here's what I observed:
The scheduled background refresh always schedules the background refresh task exactly when specified (every 15 minutes)
When it fires, a NSURLSession is created with a background configuration type
I set earliestBeginDate to now + a few seconds, since I already have an interval of 15 minutes for when I schedule the background refresh.
On a simulator, if the debugger is attached everything works fine. As soon as I detach the debugger, the background refresh task is still scheduled appropriately, but the URL session is no longer started!
On a real device, I sometimes get a NSURLSession executed in the background at a 15 minute interval, but most of the time only the application refresh task is triggered.
The spacing between each NSURLSession creation is 15 minutes and30 seconds.
Is it possible that this is just the way that it works? When updating a complication in the background from a WatchOS app, perhaps I'm exceeding the 96 complication updates that I'm trying to do in a 24 hour period? I've added code that keeps track of every complication update, both when done in the background and foreground. Not sure when the 24 hour period starts, so hopefully this'll shed some light on my issue.
But then again, this is an issue with NSURLSession and not the complication update. I'm starting to think that the NSURLSession being kicked off is a function of how many apps are on the watch, and how many are scheduling background refreshes.
@developer555,
Yes, please check out that blog and let me know. On the topic of complication updates, would you know if you're penalized for updating a complication while your app is in the foreground? Or is it only when updating in the background?
My app's data model gets updated every 2 seconds when in the foreground and I update the complication then as well.
I know that if you're updating a complication via the transferUserInfo for complications there's a budget, but what about when you're just updating it from the WatchOS app?
@developer555,
I do not schedule a URLSessionTask at all. I only schedule a background refresh. I create the URLSession background task uses the default settings. I do not use earliestBeginDate nor do I have the willBeginDelayedRequest delegate method implemented. Perhaps you're doing more than you need? Do a search on always show fresh content on WatchOS. There's a pretty good tutorial that comes up, that illustrates the bare minimum you need to get it going. You may want to compare your work with the tutorial. You're probably missing a very small amount of code.
Let me know how it turns out
@developer555,
The NSURLSession task is scheduled when the system activates my app in the background and calls the handle(_:) method in my ExtensionDelegate. When the task type is WKApplicationRefreshBackgroundTask I take 2 actions: Schedule the next background refresh to occur in 15 minutes
Call a method which then creates a background URLSession configuration, and then creates a URLSession for my network request. After creating the session, I resume it just before leaving that method.
func handle(_ bkTasks: Set<WKRefreshBackgroundTask>) {
for aTask in bkTasks {
switch aTask {
case let bkTask as WKApplicationRefreshBackgroundTask:
scheduleNextAppBackgroundRefresh()
createAndResumeURLSession()
bkTask.setTaskCompletedWithSnapshot(false)
case let urlSessionTask as WKURLSessionRefreshBackgroundTask:
/* This adds the urlSessionTask to a list, which will be used to mark
		all tasks as completed upon successful download of data
		 */
handleDownload(urlSessionTask)
default:
// Ensure that unhandled tasks are marked as complete
aTask.setTaskCompletedWithSnapshot(false)
}
}
At some point in the future I may get back data from the NSURLSession. Note that the neither the background refresh nor the URLSession task scheduling is contingent upon getting data successfully. This is because there may be network issues such as timeouts which occur. Please note that this is all boilerplate code, and you should be able to find some examples on the net
Hope this helps. Let me know
Note: This has me thinking as to whether I need to take any actions such as mark tasks completed if an error occurs during the download. I suspect I need to.
Are you behind a firewall that prevents notifications from reaching your watch and phone?
Hi Developer555,
I have 2 watches, a personal one (Series 5) and a development one (Series 4).
On my wrist, the personal watch gets data approximately every 15 minutes. Sometimes it skips for an hour. When the watch is charging I get no updates at all and my app is killed. Perhaps my app uses too much memory and that's why it's killed when the watch is charging? Not sure.
I can configure my app to download data for complication refresh every 30 minutes, 45 minutes, an hour or 2 hours.
It works well, provided that my app is suspended in the background. If the app is killed for whatever reason, even though WatchOS restarts my app and it schedules a refresh, I don't get URLSession download result until I make the app go into the foreground. Haven't gotten an answer as to whether that is intended functionality or if I need to do something.
I should point out that the amount of data I get is always less than 500 bytes.
On the development watch, I don't get the updates in as frequent a manner, but it may be because I use it only for development. I've started to wear it as well to see if that improves the refresh frequency.
So to summarize: Check the size of the download data
Check whether your app is suspended in the background when a refresh is triggered
Watch out for any files which can only be written to if the watch is not locked. WatchOS schedules your task based on how much work it does and how often your app is used
If your app has more than one complication type I'd add it to as many watch faces as possible, to see if that helps you detect the issue.
Question for you, does it work fine on the simulator? I'd try that first with Xcode attached to your app. On the simulator when connected to Xcode, refreshes will be done in a very timely fashion and there's no budget to worry about.
All the best,Sal
It appears that when the app resumes the URLSession's download task, less than 50 milliseconds later, the request fails: Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted" UserInfo={NSErrorFailingURLStringKey=https:[my request url],
NSErrorFailingURLKey=https:[my request url],
_NSURLErrorRelatedURLSessionTaskErrorKey=(
"BackgroundDownloadTask <UUID1>.<1>",
"LocalDownloadTask <UUID2>.<1>"
), _NSURLErrorFailingURLSessiontaskErrorKey=BackgroundDownloadTask <UUID3>.<1>}
How do I determine the reason why the operation is not permitted when the app is launched in the background? This seems to be the reason why my complication can't update when started by WatchOS.
Anyone care to take a guess?
Hi Andy,
Thanks for the suggestion, unfortunately I already have that. The one thing my app is doing is that when it transitions to the background it explicitly suspends timers and if started by WatchOS in the background my app does not fully initialize itself by design. I thought that was okay, especially since the complication update code is self contained and doesn't really need the app portion to initialize itself until it's in the foreground. I thought I was supposed to do that, but maybe I shouldn't?
4 years later and I have this issue as well. I take it this has not been solved?