好的,我将尽可能简单地做到这一点。启用后台模式并勾选后台获取,如下所示
每一步都遵循这个方法
应用终止时
AppDelegate.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate,CLLocationManagerDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong,nonatomic) CLLocationManager *locationManager;
@end
AppDelegate.m
#define userDef [NSUserDefaults standardUserDefaults]
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
#import "AppDelegate.h"
#import <CoreLocation/CoreLocation.h>
#import "AFNetworking.h"
#import <GoogleMaps/GoogleMaps.h>
@implementation AppDelegate{
BOOL fromTerminated;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
fromTerminated = NO;
if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) {
fromTerminated = YES;
self.locationManager = [[CLLocationManager alloc]init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.activityType = CLActivityTypeOtherNavigation;
[self.locationManager startUpdatingLocation];
}
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
if(self.locationManager){
[self.locationManager stopMonitoringSignificantLocationChanges];
self.locationManager = nil;
self.locationManager.delegate = nil;
}
self.locationManager = [[CLLocationManager alloc]init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.activityType = CLActivityTypeOtherNavigation;
if(IS_OS_8_OR_LATER) {
[self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startMonitoringSignificantLocationChanges];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
NSLog(@"locationManager didUpdateLocations: %@",locations);
if(fromTerminated){
CLLocation * newLocation = [locations lastObject];
CLLocationCoordinate2D theLocation = newLocation.coordinate;
CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy;
[userDef setObject:[NSString stringWithFormat:@"%f",theLocation.longitude] forKey:@"LONGITUDE"];
[userDef setObject:[NSString stringWithFormat:@"%f",theLocation.latitude] forKey:@"LATITUDE"];
self.myLocation = theLocation;
self.myLocationAccuracy = theAccuracy;
[self updateLocation];
}
}
-(void)updateLocation{
// call your webservice for updating
}
@end
此代码将执行以下操作-->
后台获取将触发位置更改并启动应用程序,didFInishLaunchingWithOptions 将在选项字典中使用 UIApplicationLaunchOptionsLocationKey 调用。如果它发现这意味着应用程序已终止并被唤醒以进行后台提取。现在你有 30 秒左右的时间来做你的事情。因此,您创建一个位置管理器对象并开始更新,这将触发您的 didUpdateLocations 委托方法,然后您可以调用您的方法来触发服务器或数据库中更改的位置。
在您的普通 VC 中创建另一个位置管理器对象,就像您在 didFinishiLaunchingWithOptions 方法中创建的一样,并实现委托方法 didUpdateLocation 这将一直运行,直到应用程序处于前台或后台。应用程序委托方法 hack 将在应用程序终止时触发。
干杯:)
[编辑]
当应用在前台或后台时
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ViewController ()<CLLocationManagerDelegate>
@property (nonatomic,strong) CLLocationManager *locationManager;
@end
@implementation ViewController{
}
-(void)viewDidAppear:(BOOL)animated{
if(self.locationManager == nil){
_locationManager = [CLLocationManager new];
}
_locationManager.delegate = self;
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 && [CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedWhenInUse) {
[_locationManager requestAlwaysAuthorization];
} else {
[_locationManager startUpdatingLocation];
}
}
- (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
_locationManager = nil;
CLLocation *location = [locations lastObject];
theUser.latitude = [NSString stringWithFormat:@"%f",location.coordinate.latitude];
theUser.longitude = [NSString stringWithFormat:@"%f",location.coordinate.longitude];
}
}
- (void)locationManager:(CLLocationManager*)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined: {
} break;
case kCLAuthorizationStatusDenied: {
} break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
case kCLAuthorizationStatusAuthorizedAlways: {
[_locationManager startUpdatingLocation]; //Will update location immediately
} break;
default:
break;
}
}
@end
[编辑]
要检查应用程序是否在终止状态后启动,请执行此更改并点击运行按钮并从情节提要中更改设备的位置
执行此更改,然后运行项目(在设备的调试模式下执行此操作)
并通过此更改位置,然后在applicationDidFinishLaunchingWithOptions 中设置断点,您将看到断点被命中,这意味着应用程序处于终止状态,但此位置更改已触发操作系统启动应用程序。
希望能让你明白