There are three ways that iOS programs can continue to perform tasks in the background, such as updating program interface snapshots, downloading files, and so on, even in the event of a shutdown or crash. These three methods are background fetch,remote notification and nsurlsession backgroundsessionconfigurationbackground Fetch Open
Start uibackgroundmodes background fetch in the info plist file first. Or manually edit this value
<key>UIBackgroundModes</key><array> <string>fetch</string></array>
iOS does not make background fetch by default, you need to set a time interval
-(BOOL) Application: (UIApplication *) application didfinishlaunchingwithoptions: (nsdictionary *) launchoptions{ //uiapplicationbackgroundfetchintervalminimum means to get as frequently as possible, and if you need to specify at least how much time to update, you need to give a time value Setminimumbackgroundfetchinterval:uiapplicationbackgroundfetchintervalminimum]; YES;}
Finally implement the following method in the app delegate, this method can only be completed in 30 seconds.
- (void) Application: (UIApplication *) Applicationperformfetchwithcompletionhandler: (void (^) (uibackgroundfetchresult)) completionhandler{Nsurlsessionconfiguration *sessionconfiguration = [NsurlsessionconfigurationDefaultsessionconfiguration];Nsurlsession *session = [NsurlsessionSessionwithconfiguration:sessionconfiguration];Nsurl *url = [[NsurlAllocInitwithstring:@ "Http://yourserver.com/data.json"]; Nsurlsessiondatatask *task = [session datataskwithurl:url completionhandler:^ (nsdata *data, Nsurlresponse *response, nserror *error) { if (error) { completionhandler (uibackgroundfetchresultfailed); return;} //Parse response/data to determine if new content is available BOOL Hasnewdata = ... if (hasnewdata) { completionhandler (uibackgroundfetchresultnewdata);} else { completionhandler (uibackgroundfetchresultnodata);}}]; //Start task [task resume];}
Test
- By looking at UIApplication's applicationstate
-(BOOL) Application: (UIApplication *) application didfinishlaunchingwithoptions: (nsdictionary *) launchoptions{ NSLog (%d", Uiapplicationstatebackground = = Application. YES;}
Remote Notification
In the ordinary remote notification with the CONTENT-AVAILABLE flag can be notified to the user at the same time in the background to update. The notification structure is as follows
{" APs": { "content-available" Content-id
Receiving a notification with content-available calls the following method
-(void) Application: (UIApplication *) application didreceiveremotenotification: (nsdictionary *) UserInfo fetchcompletionhandler: (void (^) (uibackgroundfetchresult)) completionhandler{ NSLog ( %@nsnumber *contentid = userinfo[@ "Content-idcompletionhandler (uibackgroundfetchresultnewdata) ;}
Background transfer task with nsurlsession
Use [nsurlsessionconfiguration backgroundsessionconfiguration] to create a background task that will still run when the app exits, crashes, or the process is turned off.
example, a remote notification is processed first, and Nsurlsessiondownloadtask is added to the Background transport service queue.
- (Nsurlsession *) backgroundurlsession{StaticNsurlsession *session =NilStaticdispatch_once_t Oncetoken;Dispatch_once (&oncetoken, ^{NSString *identifier =@ "Io.objc.backgroundTransferExample";nsurlsessionconfiguration* Sessionconfig = [NsurlsessionconfigurationBackgroundsessionconfiguration:identifier]; session = [NsurlsessionSessionwithconfiguration:sessionconfigDelegateSelfdelegatequeue:[NsoperationqueueMainqueue]]; });return session;} - (void) Application: (UIApplication *) application didreceiveremotenotification: (Nsdictionary *) UserInfo Fetchcompletionhandler: (void (^) (uibackgroundfetchresult)) completionhandler{NSLog (@ "Received Remote notification with UserInfo%@", UserInfo);NSNumber *contentid = userinfo[@ "Content-id"];NSString *downloadurlstring = [NSStringstringWithFormat:@ "http://yourserver.com/downloads/%d.mp3", [ContentIDIntvalue]];nsurl* downloadurl = [nsurl urlwithstring: Downloadurlstring]; nsurlrequest *request = [nsurlrequest requestWithURL: DownloadURL]; nsurlsessiondownloadtask *task = [[self Backgroundurlsession] downloadtaskwithrequest:request]; Task. taskdescription = [nsstring stringwithformat:@ "Podcast episode %d", [ContentID] Span class= "PL-S3" >intvalue]; //performs a resume guarantee begins the task [task resume]; completionhandler (Uibackgroundfetchresultnewdata);}
After the download is complete, call the Nsurlsessiondownloaddelegate delegate method, all of which must be implemented. Learn about the life cycle of all types of session tasks refer to the official documentation: https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/ Urlloadingsystem/nsurlsessionconcepts/nsurlsessionconcepts.html#//apple_ref/doc/uid/10000165i-ch2-sw42
#Pragma mark-nsurlsessiondownloaddelegate-(void) Urlsession: (Nsurlsession *) session Downloadtask: (Nsurlsessiondownloadtask *) Downloadtask Didfinishdownloadingtourl: (Nsurl *) location{NSLog (@ "Downloadtask:%@ Didfinishdownloadingtourl:%@ "Downloadtask. Taskdescription, location); //the file must be copied to the app's store with Nsfilemanager because the temporary file will be deleted after the method returns //... //notification UI refresh}-(void) urlsession: (nsurlsession *) session Downloadtask: (nsurlsessiondownloadtask *) Downloadtaskdidresumeatoffset: ( int64_t) fileoffset expectedtotalbytes: (int64_t) expectedTotalBytes{}-( Span class= "pl-st" >void) urlsession: (nsurlsession *) session Downloadtask: ( Nsurlsessiondownloadtask *) Downloadtask didwritedata: (int64_t) Byteswritten TotalBytesWritten :(int64_t) Totalbyteswritten totalbytesexpectedtowrite: (int64_t) totalbytesexpectedtowrite{}
After a background task is completed, if the app is not running in the foreground, you need to implement uiapplication two delegate to let the system wake up the app
- (void) Application: (UIApplication *) application handleeventsforbackgroundurlsession: (NSString *) identifier Completionhandler: (void (^) ()) completionhandler{You must re-establish a background Seesiong referenceOtherwise the nsurlsessiondownloaddelegate and Nsurlsessiondelegate methods will beThere is no delegate setting for the session and will not be called. See the backgroundurlsession aboveNsurlsession *backgroundsession = [SelfBackgroundurlsession];NSLog (@ "rejoining session with identifier%@%@", identifier, backgroundsession);Save completion handler to update the UI after the session event is processed [SelfAddcompletionhandler:completionhandlerForsession:identifier];} - (void) Urlsessiondidfinisheventsforbackgroundurlsession: (Nsurlsession *) session{NSLog (@ "Background URL session%@ finished events.", session);if (session.Configuration.Identifier) {Call the handler saved in-application:handleeventsforbackgroundurlsession: [SelfCallCompletionHandlerForSession:session.configuration.identifier]; }}- (void) Addcompletionhandler: (completionhandlertype) handler forsession: (NSString *) identifier{if ([Self.completionhandlerdictionaryObjectforkey:identifier]) {NSLog (@ "Error:got multiple handlers for a single session identifier. This should is not happen."); } [self.completionhandlerdictionary setobject:handler forkey:identifier];} -(void) Callcompletionhandlerforsession: (nsstring *) identifier{Completionhandlertype handler = [ Self.completionhandlerdictionary Objectforkey:identifier]; if (handler) {[self.completionhandlerdictionary Removeobjectforkey:identifier]; NSLog (@ "Calling completion handler for session %@", identifier); handler ();}}
Original address
Three ways to enable iOS apps to update and download data in the background