ios - 应用程序处于非事件状态时获取位置更新在 2 次更新后停止
<p><p>我正在尝试在我的应用处于非事件状态时获取位置更新(用户关闭了应用)。
2 次位置更新后,位置更新停止启动我的应用程序。
这方面的指标是我的应用中位置服务设置中的灰色箭头。</p>
<p>我正在尝试的是 <code>startMonitoringSignificantLocationChanges</code> 和 <code>regionMonitoring</code> 的组合。</p>
<ul>
<li>我在 iPhone 4 iOS 7.1.1 上进行了测试,位置更新在 2 次更新后停止。</li>
<li>我在 iPad mini WiFi+Cellular iOS 7.1.1 中进行了测试,位置更新在 1 次更新后停止,区域监控仅发送 1 个位置。</li>
</ul>
<p>我哪里错了?</p>
<p>我的代码:</p>
<p>AppDelegate.m:</p>
<pre><code>- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
.launchOptions = launchOptions;
[ stopMonitoringAllRegions];
if ( ) {
[ startMonitoringSignificantLocationChanges];
} else {
NSLog(@"Significant location change service not available.");
}
if (launchOptions) {
; // Handle new location event
UIViewController *controller = [ init];
controller.view.frame = .bounds;
UINavigationController *nvc = [ initWithRootViewController:controller];
dispatch_async(dispatch_get_main_queue(), ^{
appDelegate.window.rootViewController = nvc;
;
});
}
else {
// ...
}
return YES;
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
;
.applicationIconBadgeNumber = 0;
if (.launchOptions) {
return;
}
}
- (void)application:(UIApplication *)application handleNewLocationEvet:(NSDictionary *)launchOptions
{
NSLog(@"%s, launchOptions: %@", __PRETTY_FUNCTION__, launchOptions);
if (!) return;
if (.applicationState == UIApplicationStateActive) return;
SendLocalPushNotification(@"handleNewLocationEvet");
}
</code></pre>
<p>RegionMonitoringService.h:</p>
<pre><code>#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import "ServerApiManager.h"
@interface RegionMonitoringService : NSObject
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) NSDictionary *launchOptions;
@property (strong, nonatomic) NSDate *oldDate;
@property (strong, nonatomic) CLLocation *oldLocation;
+ (RegionMonitoringService *)sharedInstance;
- (void)startMonitoringForRegion:(CLRegion *)region;
- (void)startMonitoringRegionWithCoordinate:(CLLocationCoordinate2D)coordinate andRadius:(CLLocationDirection)radius;
- (void)stopMonitoringAllRegions;
- (void)startMonitoringSignificantLocationChanges;
- (void)stopMonitoringSignificantLocationChanges;
FOUNDATION_EXPORT NSString *NSStringFromCLRegionState(CLRegionState state);
@end
</code></pre>
<p>RegionMonitoringService.m:</p>
<pre><code>#import "RegionMonitoringService.h"
static CLLocationDistance const kFixedRadius = 250.0;
@interface RegionMonitoringService () <CLLocationManagerDelegate>
- (NSString *)identifierForCoordinate:(CLLocationCoordinate2D)coordinate;
- (CLLocationDistance)getFixRadius:(CLLocationDistance)radius;
- (void)sortLastLocation:(CLLocation *)lastLocation;
@end
@implementation RegionMonitoringService
+ (RegionMonitoringService *)sharedInstance
{
static RegionMonitoringService *_sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [ init];
});
return _sharedInstance;
}
- (instancetype)init
{
self = ;
if (!self) {
return nil;
}
_locationManager = [ init];
_locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
_locationManager.distanceFilter = kCLDistanceFilterNone;
// _locationManager.activityType = CLActivityTypeFitness;
_locationManager.delegate = self;
return self;
}
- (void)startMonitoringForRegion:(CLRegion *)region
{
NSLog(@"%s", __PRETTY_FUNCTION__);
;
}
- (void)startMonitoringRegionWithCoordinate:(CLLocationCoordinate2D)coordinate andRadius:(CLLocationDirection)radius
{
NSLog(@"%s", __PRETTY_FUNCTION__);
if (!) {
NSLog(@"Warning: Region monitoring not supported on this device.");
return;
}
if (__iOS_6_And_Heigher) {
CLRegion *region = [ initCircularRegionWithCenter:coordinate
radius:radius
identifier:];
;
}
else {
CLCircularRegion *region = [ initWithCenter:coordinate
radius:radius
identifier:];
;
}
SendLocalPushNotification();
}
- (void)stopMonitoringAllRegions
{
NSLog(@"%s", __PRETTY_FUNCTION__);
if (_locationManager.monitoredRegions.allObjects.count > 1) {
for (int i=0; i<_locationManager.monitoredRegions.allObjects.count; i++) {
if (i == 0) {
NSLog(@"stop monitor region at index %d", i);
CLRegion *region = (CLRegion *)_locationManager.monitoredRegions.allObjects;
;
}
}
}
}
- (void)startMonitoringSignificantLocationChanges
{
NSLog(@"%s", __PRETTY_FUNCTION__);
;
}
- (void)stopMonitoringSignificantLocationChanges
{
NSLog(@"%s", __PRETTY_FUNCTION__);
;
}
- (NSString *)identifierForCoordinate:(CLLocationCoordinate2D)coordinate
{
NSLog(@"%s", __PRETTY_FUNCTION__);
return ;
}
FOUNDATION_EXPORT NSString *NSStringFromCLRegionState(CLRegionState state)
{
NSLog(@"%s", __PRETTY_FUNCTION__);
if (__iOS_6_And_Heigher) {
return @"Support only iOS 7 and later.";
}
if (state == CLRegionStateUnknown) {
return @"CLRegionStateUnknown";
} else if (state == CLRegionStateInside) {
return @"CLRegionStateInside";
} else if (state == CLRegionStateOutside) {
return @"CLRegionStateOutside";
} else {
return ;
}
}
- (CLLocationDistance)getFixRadius:(CLLocationDistance)radius
{
if (radius > _locationManager.maximumRegionMonitoringDistance) {
radius = _locationManager.maximumRegionMonitoringDistance;
}
return radius;
}
- (void)sortLastLocation:(CLLocation *)lastLocation
{
NSLog(@"%s, %@", __PRETTY_FUNCTION__, lastLocation);
self.oldDate = lastLocation.timestamp; // Get new date
NSTimeInterval seconds = fabs(); // Calculate how seconds passed
NSInteger minutes = seconds * 60; // Calculate how minutes passed
if (lastLocation && self.oldLocation) { // New & old location are good
if ( >= 200 || minutes >= 30) { // Distance > 200 or 30 minutes passed
[ saveLocation:lastLocation]; // Send location to server
}
}
else { // We just starting location updates
[ saveLocation:lastLocation]; // Send new location to server
}
self.oldLocation = lastLocation; // Set old location
}
#pragma mark - CLLocationManagerDelegate Methods
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(@"%s, %@", __PRETTY_FUNCTION__, locations);
CLLocation *lastLocation = (CLLocation *)locations.lastObject;
CLLocationCoordinate2D coordinate = lastLocation.coordinate;
if (lastLocation == nil || coordinate.latitude== 0.0 || coordinate.longitude == 0.0) {
return;
}
];
;
}
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
NSLog(@"%s, currentLocation: %@, regionState: %@, region: %@",
__PRETTY_FUNCTION__, manager.location, NSStringFromCLRegionState(state), region);
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
{
NSLog(@"%s, REGION: %@", __PRETTY_FUNCTION__, region);
;
}
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
}
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
NSLog(@"%s, REGION: %@", __PRETTY_FUNCTION__, region);
;
];
CLLocation *lastLocation = manager.location;
CLLocationCoordinate2D coordinate = lastLocation.coordinate;
if (lastLocation == nil || coordinate.latitude== 0.0 || coordinate.longitude == 0.0) {
return;
}
;
}
@end
</code></pre>
<p> <img src="/image/qLZCM.png" alt="enter image description here"/> </p>
<p> <img src="/image/QXSkM.png" alt="enter image description here"/> </p>
<p><strong>编辑 1:</strong></p>
<p>经过几次测试后,我用多种设备(iPhone 5s、iPad mini、iPhone 4)对汽车进行了很多实时测试,结果如下:</p>
<ol>
<li>在一种情况下,iPad mini 和 iPhone 4 会在应用未运行几分钟后停止更新位置,并且小箭头变为灰色。</li>
<li>当 WiFi 关闭时,准确性很差,位置更新很少。</li>
</ol>
<p><strong>编辑 2:</strong></p>
<p>好的,经过大量的驾驶和四处走动并对其进行测试,到目前为止,它的工作原理就像一个魅力。
我设法使它工作,结合 <code>significantLocationChanges</code> 和区域监控,总是在我当前位置周围注册一个地理围栏,并总是在新的 <code>UIApplicationLaunchOptionsLocationKey</code> 到来时开始重大的位置更改。
请注意,关闭 wifi 会使准确性非常低,甚至有时无法正常工作。</p>
<p>我的代码中有错误吗?</p></p>
<br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
<p><p>来自苹果 <a href="https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManager_Class/CLLocationManager/CLLocationManager.html#//apple_ref/occ/instm/CLLocationManager/startMonitoringSignificantLocationChanges" rel="noreferrer noopener nofollow">docs</a>可以看出,更新的发送频率并不高于每 <strong>5 分钟</strong> 和 <strong>500 米</strong> 的位置变化:</p>
<p><code>只要设备从之前的通知移动 500 米或更远,应用程序就会收到通知。它不应期望通知的频率超过每五分钟一次。如果设备能够从网络中检索数据,则位置管理器更有可能及时发送通知。</code></p>
<p>即使应用处于非事件状态,您也会收到更新。对您的另一个提示可能是 oyu 可以在模拟器中测试位置,而不是使用真实设备,这样您就不必到外面进行测试并且仍然可以检查您的日志。在模拟器菜单中,选择<em>Debug --> Location</em>。</p></p>
<p style="font-size: 20px;">关于ios - 应用程序处于非事件状态时获取位置更新在 2 次更新后停止,我们在Stack Overflow上找到一个类似的问题:
<a href="https://stackoverflow.com/questions/24277690/" rel="noreferrer noopener nofollow" style="color: red;">
https://stackoverflow.com/questions/24277690/
</a>
</p>
页:
[1]