应用程序终止时未调用CLLocationManager`didUpdateToLocation`

时间:2017-10-17 18:21:51

标签: ios objective-c cocoa-touch geolocation core-location

我的应用程序终止时,我正在尝试回复位置更新。 Apple's documentation州:

  

iOS支持将位置事件传递给应用程序   暂停或不再运行。

它还声明startUpdatingLocation

  

可以在后台模式中使用位置更新是

但是,仅当应用程序在前台或后台运行时,才会调用didUpdateToLocation方法。当我终止应用程序时,它永远不会醒来处理位置更新。我已经在几个模拟设备(iPhone 6,7,8,X)以及真正的iPhone 5s上测试了这个。我还确认正在调用setAllowsBackgroundLocationUpdates

AppDelegate.m

#import "AppDelegate.h"
#import "RNFIRMessaging.h"
#import <CoreLocation/CoreLocation.h>

#import <React/RCTBridgeModule.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import "NoteManager.h"

@implementation AppDelegate {
  UIApplication *_app;
  NoteManager *_noteManager;
  CLLocationManager* _locationManager;
}

- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  NSLog(@"--- Initializing application");
  _app = application;

  id<RCTBridgeDelegate> moduleInitialiser = self;
  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:moduleInitialiser launchOptions:launchOptions];

  RCTRootView *rootView = [[RCTRootView alloc]
    initWithBridge:bridge
    moduleName:@"GoNote"
    initialProperties:nil
  ];
  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];

  [FIRApp configure];
  [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
  [self setupLocationManager];

  return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
  // return [NSURL URLWithString:@"http://192.168.1.177:8081/index.ios.bundle?platform=ios"];
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
}

- (NSArray *)extraModulesForBridge:(RCTBridge *)bridge {
  NSLog(@"--- extraModulesForBridge");
  // Initialize our native modules here
  _noteManager = [[NoteManager alloc] initWithApp:_app];
  return @[
    _noteManager
  ];
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
  NSLog(@"--- pushNotifications willPresentNotification");
  [RNFIRMessaging willPresentNotification:notification withCompletionHandler:completionHandler];
}

#if defined(__IPHONE_11_0)
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
  NSLog(@"--- pushNotifications didReceiveNotificationResponse");
  [RNFIRMessaging didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
}
#else
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler {
  NSLog(@"--- pushNotifications didReceiveNotificationResponse");
  [RNFIRMessaging didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
}
#endif

//You can skip this method if you don't want to use local notification
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
  NSLog(@"--- pushNotifications didReceiveLocalNotification");
  [RNFIRMessaging didReceiveLocalNotification:notification];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
  NSLog(@"--- pushNotifications didReceiveLocalNotification");
  [RNFIRMessaging didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

- (void) applicationDidEnterBackground:(UIApplication *)application {
  NSLog(@"--- applicationDidEnterBackground");
  [_locationManager stopUpdatingLocation];

  __block UIBackgroundTaskIdentifier bgTask = [_app beginBackgroundTaskWithExpirationHandler:^{
    bgTask = UIBackgroundTaskInvalid;
  }];

  [NSTimer
    scheduledTimerWithTimeInterval: 10.0
    target: self
    selector: @selector(startTrackingBg)
    userInfo: nil
    repeats: YES
  ];
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError*)error {
  NSLog(@"--- (NoteManager) locationManager didFailWithError %@", error);
}

- (void) setupLocationManager {
  NSLog(@"--- setupLocationManager");
  CLLocationManager* locationManager = _locationManager = [[CLLocationManager alloc] init];
  if([locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) {
    NSLog(@"--- setAllowsBackgroundLocationUpdates:YES");
    [locationManager setAllowsBackgroundLocationUpdates:YES];
  } else {
    NSLog(@"--- setAllowsBackgroundLocationUpdates:NO");
  }
  [locationManager setDelegate:self];
  [locationManager requestAlwaysAuthorization];
  [locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
  [locationManager setDistanceFilter:10];
  [locationManager setPausesLocationUpdatesAutomatically:NO];
  [locationManager startUpdatingLocation];
}

- (void) startTrackingBg {
#if !TARGET_OS_TV
  NSLog(@"--- startTrackingBg");
  [_locationManager startUpdatingLocation];
#endif
}

- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
  NSLog(@"--- didUpdateToLocation");
  if(_noteManager != nil) {
    [_noteManager updateLocation:newLocation];
  }
}

@end

AppDelegate.h

#import <UIKit/UIKit.h>
#import <React/RCTBridgeDelegate.h>
#import <CoreLocation/CoreLocation.h>
@import UserNotifications;

@interface AppDelegate : UIResponder <UIApplicationDelegate, UNUserNotificationCenterDelegate, RCTBridgeDelegate, CLLocationManagerDelegate>

@property (nonatomic, strong) UIWindow *window;

@end

1 个答案:

答案 0 :(得分:2)

这并不完全符合您的要求。使用

监控重要位置更改时,位置更新会起作用
  

startMonitoringSignificantLocationChanges()

在这里阅读这个答案,其中某人正在尝试几乎相同的事情 - Restart location updates from the background

您可以在此处阅读此处的实施https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html