Because the iOS system is "pseudo background" mode, when the home button is pressed, such as the program does not do anything, the application will have 5 seconds of execution buffer time, the random program is suspended, all the task terminal, including timer and location update operation, but the program open background mode switch, some tasks can be performed in the background, such as audio, Location, bluetooth, download, VOIP, even so, the program's background runs can be extended for up to 594 seconds (about 10 minutes). Unfortunately, the program is likely to be rejected when the app is on the shelves after declaring the background mode. Based on this, I've developed a way to keep timers and positions running when the app enters the foreground without having to declare the background mode.
The implementation principle is as follows:
Using the notification mechanism of iOS, send a notification when the program enters the background and back to the foreground, and record the current time into the background and the current time to return to the foreground, calculate the time interval between the two, add the listener to the program wherever needed, and execute the code block in the listening method. The parameters within the code block are the notification object and the calculated time interval. Take the timer as an example, after the program into the background, the timer stopped running, at this time using the above method, in the program to return to the foreground when the code block content, the program into the background when the timer's current time interval plus code block time interval parameters can make the timer accurate timing. Nonsense not much to say, on the code:
In the APPDELEGATE.M implementation file:
- (void) Applicationdidenterbackground: (UIApplication *) Application {//Use the method to release the shared resources, save user data, invalidate timers, and store enough application state in Formation to the restore your application to the it is terminated later. //If Your application supports background execution, this method is called instead of Applicationwillterminate:when th E user quits.[[Nsnotificationcenter Defaultcenter]postnotificationname:uiapplicationdidenterbackgroundnotificationObject: nil];}- (void) Applicationwillenterforeground: (UIApplication *) Application {//Called as part of the transition from the background to the active state; Here you can undo many of the changes made On entering the background.[[Nsnotificationcenter Defaultcenter]postnotificationname:uiapplicationwillenterforegroundnotificationObject: nil];}
Code Description: After the program into the background, using the system notification mechanism to notify the program into the background and back to the foreground, the listener object for all objects.
Then define a handler to enter the background class Ythandlerenterbackground
////YTHandlerEnterBackground.h//Timeshare Rental////Created by Cauchy's spectrum on 17/2/24.//Copyright 2017 Cauchy's spectrum. All rights reserved.//#import<Foundation/Foundation.h>#import<UIKit/UIKit.h>/** Enter the backend block typedef*/typedefvoid(^ythandlerenterbackgroundblock) (Nsnotification *_nonnull Note, nstimeinterval staybackgroundtime);/** processed into the background and calculated to stay in the background time interval class*/@interfaceYthandlerenterbackground:nsobject/** Add observer and process background*/+ (void) Addobserverusingblock: (Nullable ythandlerenterbackgroundblock) block;/** Remove Background viewer*/+ (void) Removenotificationobserver: (NullableID) Observer;@end
In the YTHANDLERENTERBACKGROUND.M implementation file:
////YTHANDLERENTERBACKGROUND.M//Timeshare Rental////Created by Cauchy's spectrum on 17/2/24.//Copyright 2017 Cauchy's spectrum. All rights reserved.//#import "YTHandlerEnterBackground.h"@implementationYthandlerenterbackground+ (void) Addobserverusingblock: (ythandlerenterbackgroundblock) block {__block cfabsolutetime enterbackgroundtime; [[Nsnotificationcenter defaultcenter]addobserverforname:uiapplicationdidenterbackgroundnotificationObject: Nil Queue:nil usingblock:^ (nsnotification *_nonnull Note) { if(! [Note.ObjectIskindofclass:[uiapplicationclass]]) {enterbackgroundtime=cfabsolutetimegetcurrent (); } }]; __block Cfabsolutetime Enterforegroundtime; [[Nsnotificationcenter defaultcenter]addobserverforname:uiapplicationwillenterforegroundnotificationObject: Nil Queue:nil usingblock:^ (nsnotification *_nonnull Note) { if(! [Note.ObjectIskindofclass:[uiapplicationclass]]) {enterforegroundtime=cfabsolutetimegetcurrent (); Cfabsolutetime TimeInterval= enterforegroundtime-Enterbackgroundtime; Block?block (note, timeinterval): nil; } }];}+ (void) Removenotificationobserver: (ID) Observer {if(!observer) { return; } [[Nsnotificationcenter defaultcenter]removeobserver:observer Name:uiapplicationdidenterbackgroundnotification Object: nil]; [[Nsnotificationcenter Defaultcenter]removeobserver:observer Name:uiapplicationwillenterforegroundnotification Object: nil];}@end
This class implements the method used to add notification listeners and handles background and remove notification listeners, and it is important to note that in the Addobserverusingblock method, there must be an if (![ Note. Object Iskindofclass:[uiapplication class]]) , otherwise the code block in the addobserverforname method executes several times, and this code executes two times. The Addobserverusingblock method is to invoke the Add notification listener in the Viewwillappear method, and to invoke the Remove notification listener in the Viewwilldisappear method.
For example, in a Nstimer controller that uses a timer:
-(void ) Viewwillappear: (BOOL) animated {[Super viewwillappear:animated]; [Ythandlerenterbackground addobserverusingblock: ^ (nsnotification * _nonnull Note, Nstimeinterval staybackgroundtime) {self.renttimerinterval = Self.renttimerinterval-staybackgroundtime; }];} -(void
I defined a Timer object with a countdown time of 5 minutes, and defined a timer for the current countdown interval renttimerinterval property, in the Add Notification Listener code block,renttimerinterval equals the countdown interval when entering the background minus the time interval that the program stays in the background, and when the timer returns to the foreground, the time interval for the timer is constant. Although the timer does not run continuously in the background, using this method also implements the correct instant of the timer.
Similarly, when the program has a location update function, when the program enters the background, the location service object will automatically stop updating, at this time the practice is still called the above two processing into the background, so that the program into the background, and then start positioning:
In a class that requires a location update:
- (void) Viewwillappear: (BOOL) animated {[Super viewwillappear:animated]; Self.locservice.Delegate=Self ; [Self.locservice Startuserlocationservice]; //Go backstage and go back to the foreground and start positioning again.[Ythandlerenterbackground addobserverusingblock:^ (Nsnotification *_nonnull Note, Nstimeinterval staybackgroundtime) {[Self.locservice startuserlocationservice]; }];}- (void) Viewwilldisappear: (BOOL) animated {[Super viewwilldisappear:animated]; //Stop PositioningSelf.locservice.Delegate=Nil; [Self.locservice Stopuserlocationservice]; //To remove background snooping[Ythandlerenterbackground removenotificationobserver:self];}
Baidu Map SDK is used here.
With this approach, tasks such as timers and location updates that need to be run in the background can meet the needs, but the trouble is that the two methods are called in any required class, and you can add other parameters to your needs, when the program enters the background and back to the foreground (the notification object parameter is required). For example, save the operation before entering the background and so on. or define different ways to add notification listeners to meet different requirements.
iOS fixes an issue where timers and location updates stop after the app enters the background