Not sure what happens to my apps objects when using NSURLSession in background - what state is my app in?
- by Avner Barr
More of a general question - I don't understand the workings of NSURLSession when using it in "background session mode". I will supply some simple contrived example code.
I have a database which holds objects - such that portions of this data can be uploaded to a remote server. It is important to know which data/objects were uploaded in order to accurately display information to the user. It is also important to be able to upload to the server in a background task because the app can be killed at any point.
for instance a simple profile picture object:
@interface ProfilePicture : NSObject
@property int userId;
@property UIImage *profilePicture;
@property BOOL successfullyUploaded; // we want to know if the image was uploaded to out server - this could also be a property that is queryable but lets assume this is attached to this object
@end
Now Lets say I want to upload the profile picture to a remote server - I could do something like:
@implementation ProfilePictureUploader
-(void)uploadProfilePicture:(ProfilePicture *)profilePicture completion:(void(^)(BOOL successInUploading))completion
{
NSUrlSession *uploadImageSession = ..... // code to setup uploading the image - and calling the completion handler;
[uploadImageSession resume];
}
@end
Now somewhere else in my code I want to upload the profile picture - and if it was successful update the UI and the database that this action happened:
ProfilePicture *aNewProfilePicture = ...;
aNewProfilePicture.profilePicture = aImage;
aNewProfilePicture.userId = 123;
aNewProfilePicture.successfullyUploaded = NO;
// write the change to disk
[MyDatabase write:aNewProfilePicture];
// upload the image to the server
ProfilePictureUploader *uploader = [ProfilePictureUploader ....];
[uploader uploadProfilePicture:aNewProfilePicture completion:^(BOOL successInUploading) {
if (successInUploading) {
// persist the change to my db.
aNewProfilePicture.successfullyUploaded = YES;
[Mydase update:aNewProfilePicture]; // persist the change
}
}];
Now obviously if my app is running then this "ProfilePicture" object is successfully uploaded and all is well - the database object has its own internal workings with data structures/caches and what not. All callbacks that may exist are maintained and the app state is straightforward.
But I'm not clear what happens if the app "dies" at some point during the upload. It seems that any callbacks/notifications are dead. According to the API documentation- the uploading is handled by a separate process. Therefor the upload will continue and my app will be awakened at some point in the future to handle completion. But the object "aNewProfilePicture" is non existant at that point and all callbacks/objects are gone. I don't understand what context exists at this point. How am I supposed to ensure consistency in my DB and UI (For instance update the "successfullyUploaded" property for that user)? Do I need to re-work everything touching the DB or UI to correspond with the new API and work in a context free environment?