Post

Replies

Boosts

Views

Activity

Reply to Complication stops updating when Apple Watch is on the charger
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.
Sep ’20
Reply to WatchOS: background refresh file is downloaded but didFinishDownloadingTo: never called...
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.
Sep ’20
Reply to Cannot start debug session on Watch simulator using Xcode 12 (12A7209)
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.
Sep ’20
Reply to watchOS: Background URL session always takes over an hour to return
@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.
Sep ’20
Reply to watchOS: Background URL session always takes over an hour to return
@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?
Sep ’20
Reply to watchOS: Background URL session always takes over an hour to return
@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
Sep ’20
Reply to WatchOS: background refresh file is downloaded but didFinishDownloadingTo: never called...
@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 &#9;&#9;all tasks as completed upon successful download of data &#9;&#9; */ 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.
Sep ’20
Reply to watchOS: Background URL session always takes over an hour to return
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
Aug ’20
Reply to Complication stops updating when Apple Watch is on the charger
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 &lt;UUID1&gt;.&lt;1&gt;", "LocalDownloadTask &lt;UUID2&gt;.&lt;1&gt;" ), _NSURLErrorFailingURLSessiontaskErrorKey=BackgroundDownloadTask &lt;UUID3&gt;.&lt;1&gt;} 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?
Aug ’20
Reply to Complication stops updating when Apple Watch is on the charger
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?
Aug ’20