startMonitoringSignificantLocationChanges的问题

时间:2014-04-04 12:28:17

标签: ios ios7 cllocationmanager

我正在使用CLLocationManager的“startMonitoringSignificantLocationChanges”方法。此方法在后台状态和活动状态下运行良好,但在应用程序终止时则无法运行。上述方法的文档说:

“如果您启动此服务并且您的应用程序随后终止,则系统会在新事件到来时自动将应用程序重新启动到后台。”

但我无法在我的代码中实现它。我在Stack Overflow中经历了很多QnA,并且尝试了一些解决方案,但还没有成功。 我的iOS版本是7.1。

我的代码:

ViewController.m

//Created sharedInstance of my class

+(ViewController *)sharedInstance { <br/><br/>
    static ViewController *sharedViewController = nil; <br/> 
    @synchronized(self) { <br/>
        if (sharedViewController == nil) { <br/>
            sharedViewController = [[self alloc] init]; <br/>
        } <br/>
    } <br/>
    return sharedViewController; <br/>
}

//按钮单击启动startMonitoringSignificantLocationChanges方法

- (IBAction)clickedGetCurrentLocation:(id)sender { <br/>
    locationManager.delegate = self; <br/>
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;

    [self startMonitoringSignificantLocationChanges]; <br/>
}

- (void) startMonitoringSignificantLocationChanges
{ <br/>
    [locationManager startMonitoringSignificantLocationChanges]; <br/>
}

#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{ <br/>
    NSLog(@"didFailWithError: %@", error); <br/>
    UIAlertView *errorAlert = [[UIAlertView alloc]
                               initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; <br/>
    [errorAlert show];

    [locationManager stopUpdatingLocation]; <br/>
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {

    CLLocation *currentLocation = locations[0];

    if (currentLocation != nil) { <br/>
        longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude]; <br/>
        latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude]; <br/>
    }

    // Reverse Geocoding <br/>
    [geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) { <br/>
        if (error == nil && [placemarks count] > 0) { <br/>
            placemark = [placemarks lastObject]; <br/>
            addressLabel.text = [NSString stringWithFormat:@"%@ %@\n%@ %@\n%@\n%@",
                                 placemark.subThoroughfare, placemark.thoroughfare,
                                 placemark.postalCode, placemark.locality,
                                 placemark.administrativeArea,
                                 placemark.country]; <br/>            
        } else { <br/>
            NSLog(@"%@", error.debugDescription);  <br/>
        } <br/>
    } ];

    UILocalNotification* localNotification = [[UILocalNotification alloc] init]; <br/>

    NSString *message = [NSString stringWithFormat:@"Location Changed To (%@, %@)", [latitudeLabel text], [longitudeLabel text]]; <br/>
    localNotification.alertBody = message; <br/>
    localNotification.fireDate = [NSDate date]; <br/>
    localNotification.alertAction = @"Location Change Detected"; <br/>
    localNotification.timeZone = [NSTimeZone timeZoneWithName:@"Asia/India"]; <br/>
    localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;

    [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];    

    [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadData" object:self];
}

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ <br/>
    if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) { <br/>
        [[ViewController sharedInstance] startMonitoringSignificantLocationChanges]; <br/>
    }    <br/>

    UILocalNotification *locationNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];

    if (locationNotification) { <br/>
        application.applicationIconBadgeNumber = 0; <br/>
    }

    return YES; <br/>
}

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{ <br/>
    UIApplicationState state = [application applicationState]; <br/>
    if (state == UIApplicationStateActive) { <br/>
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Location"
                                                        message:notification.alertBody
                                                       delegate:self cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil]; <br/>
        [alert show]; <br/>
    }

    // Set icon badge number to zero <br/><br/>
    application.applicationIconBadgeNumber = 0;
}

2 个答案:

答案 0 :(得分:0)

当IOS收到位置更新,并在终止应用后重新生成您的应用时,让它知道由于位置服务而重新生成。那么你需要在diddidFinishLaunchingWithOptions方法中重新启动后台位置服务,如下所示:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) {
        [[LocationController sharedInstance] startMonitoringSignificantLocationChanges];
    }
    return YES;
}

答案 1 :(得分:0)

根据我的经验,由于重要的位置更改,应用程序无法从终止启动,但GeoFencing可以解决问题。 如果设置用户进入/退出的围栏,您将从终止启动到响应事件〜30秒的后台时间(取决于设备类型)。