Updating complication with Swift 3 and background task - swift

For watchOS 3, Apple suggests updating the complication with WKRefreshBackgroundTask instead of using getNextRequestedUpdateDate.
How can I determine the time between two updates using the new approach?
I would only hack my data requesting (from an url) into getCurrentTimelineEntry and would update the complication, but I think that's not really what Apple would recommend.
A short code example would be a big help.

I generally covered this in a different answer, but I'll address your specific question here.
You're right that you shouldn't hack the complication controller to do any (asynchronous) fetching. The data source should only be responsible for returning existing data on hand as requested by the complication server. This was true for watchOS 2, and is still true in watchOS 3.
For watchOS 3, each background refresh can schedule the next one.
Overview of the process:
In your particular case, you can wait until your WKURLSessionRefreshBackgroundTask task finishes its downloading. At that point, schedule the next background refresh before completing your existing background task.
At that future time, your extension will be woken up again to start the entire background process again to:
Request new data from your web service
Handle the reply and update your data store
Tell the complication to update itself (which will use the new data on hand).
Update the dock snapshot
Schedule an upcoming background refresh task
Mark your current task as complete.
You can even chain a series of different background sub-tasks where each sub-task handles a separate aspect of a refresh cycle, and is responsible for scheduling the following sub-task.
Sample code:
If you haven't seen it, Apple provides its WatchBackgroundRefresh sample code to demonstrate part of this. You can use
WKExtension.shared().scheduleBackgroundRefresh(withPreferredDate:userInfo:)
to schedule (either the initial, or) a future task before the present task completes.
Although their example uses a refresh button to schedule the next background refresh, the concept is the same, whether it is a user action or background task that schedules the next request).

Related

Is there a standard / built-in way to handle race conditions with CKFetchRecordZoneChangesOperation?

I'm building my first CloudKit application, and am using CKFetchRecordZoneChangesOperation on startup to get any new records changed while the current device was offline.
I am also calling CKFetchRecordZoneChangesOperation when I receive a subscription notification of changes.
It is possible the subscription notification could come in before the startup call finishes. I am currently using a lock to prevent the 2nd call from starting until the recordZoneFetchCompletionBlock handler is called, signalling that the first one is done. This works, but it also smells a bit hacky.

Android Async Task does not update UI when application is in background

The application I am working on downloads and parses a large xml file to populate UI elements, namely search and a spinner. This is done through an async task. If the user decides to switch out of the application during this, the information is downloaded correctly, but then when the application is resumed, the UI will not be updated.
Is this because the changes can't be made while the application is not active? What is the best way to go about checking whether the UI was not updated on resume? Or instead should I be doing something with the Async task, checking whether the UI thread is available? I'm having a hard time debugging this because it involves leaving the application which ends the debugger.
You can achieve this scenario through the broadcast receive.
Follow the step:
Solution 1:
Step 1;
Register the broadcast receiver before executing the Asyntask.
Step 2:
send Broadcast in onPostExecute method of Asyntask.
step 3:
And then you can able receive your broadcast message in your activity.
and do whatever you want.
Solution 2:
Otherwise you can use Interface Call back for this Scenario.
Hope It will help you.
It should'nt. App being in background means View objects may or may not be there. Actually the entire process may be stopped or just deleted by android.
Use a Service to truly do processing in background. When processing is complete but UI is not there, post a notification to let user know, OR, save the results and provide it to UI the next time it binds to your service and ask for same thing (a.k.a caching).
The application in background may not be live. The O.S may destroy it in case of memory constrains.
The trick is to try an alternate logic.
When the application moves from background to foreground onresume() is called ,you could try saving the data to db and update the content on the resume call.
FYI.onPause() and OnResume() is called when the application goes background and foreground respectively.

The difference between suspend and suspendAll

What is the difference between suspend and suspendAll in SCORM 2004 3rd ED?
Can I suspend more than one activity in one session?
In SCORM 2004, "suspending" something indicates that you want to preserve it's state. Think of it conceptually as a pause button, a way to stop and come back to the same place later.
"Suspend" and "SuspendAll" are used in two different contexts. As you probably are aware by now, the SCORM run-time and SCORM sequencing books are separate but related.
"Suspend" is a concept from the run-time book (if I read and understand your question correctly). Setting cmi.exit to suspend indicates that you want to save this set of run-time data for the current SCO so that when the activity is relaunched the data will still be available.
"SuspendAll" is a concept from the sequencing book. It is a navigation request that indicates the learner wants to pause and exit the entire activity tree. When a suspendAll navigation request is processed, the activity tree state (the sequencing data) is preserved and when the course is relaunched, the learner will resume from the current activity.
Some other thing to note:
suspendAll is not related to the preservation of run-time data. If you issue a suspendAll navigation request, that won't in itself preserve the current activity's run-time data.
To confuse matters a bit further, there are two more ways the word "suspend" is used:
"The Suspended Activity" - The activity that was current when a suspendAll navigation request was issued. This is the activity that will be resumed when the course is relaunched.
"Suspended" - a property of every activity that indicates whether it was last exited in a suspended state.
So, to answer your second question, there can only be one "suspended activity" at any given time, but many activities can be "suspended".

Data driven view iOS app

I am new to objective-c/cocoa programming. I am making an application which is to constantly sync with a server and keep its view updated.
Now in a nutshell, heres what I thought of: Initiate an NSTimer to trigger every second or two, contact the server, if there is a change, update the view. Is this a good way of doing it?
I have read elsewhere that you can have a thread running in the background which monitors the changes and updates the view. I never worked with threads before and I know they can be quite troublesome and you need a good amount of experience with memory management to get most out of them.
I have one month to get this application done. What do you guys recommend? Just use an NSTimer and do it the way I though of...or learn multithreading and get it done that way (but keep in mind my time frame).
Thanks!
I think using separate thread in this case would be too much. You need to use threads when there is some task that runs for considerable amount of time and can freeze your app for some time.
In your case do this:
Create timer and call some method (say update) every N seconds.
in update send asynchronous request to server and check for any changes.
download data using NSURLConnection delegate and parse. Note: if there is probability that you can receive a huge amount of data from server and its processing can take much time (for example parsing of 2Mb of XML data) then you do need to perform that is a separate thread.
update all listeners (appropriate view controllers for example) with processed data.
continue polling using timer.
Think about requirements. The most relevant questions, IMO, are :
does your application have to get new data while running in background?
does your application need to be responsive, that is, not sluggish when it's fetching new data?
I guess the answer to the first question is probably no. If you are updating a view depending on the data, it's only required to fetch the data when the view is visible. You cannot guarantee always fetching data in background anyway, because iOS can always just kill your application. Anyway, in your application's perspective, multithreading is not relevant to this question. Because either you are updating only in foreground or also in background, your application need no more than one thread.
Multithreading is relevant rather to the second question. If your application has to remain responsive while fetching data, then you will have to run your fetching code on a detached thread. What's more important here is, the update on the user interface (like views) must happen on the main thread again.
Learning multithreading in general is something indeed, but iOS SDK provides a lot of help. Learning how to use operation queue (I guess that's the easiest to learn, but not necessarily the easiest to use) wouldn't take many days. In a month period, you can definitely finish the job.
Again, however, think clearly why you would need multithreading.

Saving painting app data to cope with interruptions on iPhone?

I'm making an iPhone bitmap painting app. I want to support about five 1024x768 layers (~15Mb of data). My problem is that I do not know what strategy to use for saving the user's document to cope with my app being interrupted.
My document file format at the moment is to save each layer as a .png file and then save a short text file that contains the layer metadata. My problem is that, if the app is interrupted by something like a phone call, I'm unlikely going to have enough time for my app to be able to save all the data to disk as saving all the .png files can take ~10 seconds. What options do I have?
I've considered adding an autosave feature that would be called every five minutes. In the worst case, the user will lose a few minutes of work if the app fails to save on interruption (which isn't ideal).
An idea I've considered is to keep track of which layers have changed since the last autosave and only update the layer files that need to be updated. This means that, when interrupted, my app might only need to save one layer in the typical case. However, the worse case is still having to save several layers.
I'm not sure what to do. On a practical note, I've noticed many popular iPhone painting apps with good reviews will lose the current document progress if interrupted with a phone call. I'm beginning to doubt there is a way to solve this particular problem and that I might just have to go with something less than ideal.
The IOS4 SDK provides support for long-running background tasks, which would be the perfect place to save your layers. From the documentation:
You can use task completion to ensure that important but potentially long-running operations do not end abruptly when the user leaves the application. For example, you might use this technique to save user data to disk or finish downloading an important file from a network server.
Any time before it is suspended, an application can call the beginBackgroundTaskWithExpirationHandler: method to ask the system for extra time to complete some long-running task in the background. If the request is granted, and if the application goes into the background while the task is in progress, the system lets the application run for an additional amount of time instead of suspending it. (The backgroundTimeRemaining property of the UIApplication object contains the amount of time the application has to run.)
I'm not sure if this is feasible (you don't state how the user interacts with the layers, or indeed if this interaction is transparent from their perspective), but as a suggestion why not simply save the "active" layer out (via a background thread) when the user switches layers, as you'd then only need to save a single layer when your app is backgrounded.