CLLocationManager SignificantLocationChanges Force Refresh

I have an app that uses CLLocation manager and I need ability to force a location event to be delivered. Apple documentation states...

After returning a current location fix, the receiver generates update events only when a significant change in the user's location is detected. For example, it might generate a new event when the device becomes associated with a different cell tower. It does not rely on the value in the distanceFilter property to generate events. Calling this method several times in succession does not automatically result in new events being generated. Calling stopMonitoringSignificantLocationChanges in between, however, does cause a new initial event to be sent the next time you call this method.

So I read that as I can call stopMonitoringSignificantLocationChanges and then startMonitoringSignificantLocationChanges and receive a location event, however, in practice this is not working. See code below (I've removed pieces so as to not disclose private reverse geo APIs). This is a wrapper class to combine reverse geo with CLLocationManager. In my demo app I am calling beginMonitoringSignificantChanges and then stopMonitoringSignificantChanges and I am only seeing -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations called when I change locations or when I first install the app, not when I stop and start. Any thoughts?

//
//  TTGeoWrapper.m
//  LocationManagementDemoApp
//
//  Created by Kyle Jurick on 12/17/12.
//  Copyright (c) 2012 Kyle Jurick. All rights reserved.
//

#import "TTGeoWrapper.h"
#import "OpenXML.h"

@implementation TTGeoWrapper
-(id)initWith//removed code
{
    self = [super init];
    if (self) {
        //removed code
        _transactionTimeout=30;
        //removed code
        locationManager = [[CLLocationManager alloc] init];
        locationManager.delegate = self;
        authorizationStatus = [CLLocationManager authorizationStatus];
        if (authorizationStatus != kCLAuthorizationStatusAuthorized) {
            ableToMonitorLocation = false;
        }
        else
        {
            ableToMonitorLocation = true;
        }

    }

    return self;
}

-(void)dealloc
{
    locationManager.delegate = nil;
}

-(void)beginMonitoringSignificantChanges
{
    //if (ableToMonitorLocation) {
        [locationManager startMonitoringSignificantLocationChanges];
    /*}
    NSMutableDictionary *requestFailureUserInfo = [[NSMutableDictionary alloc] init];
    [requestFailureUserInfo setValue:@"NOT AUTHORIZED" forKey:@"FAILURE REASON"];
    [requestFailureUserInfo setValue:[NSString stringWithFormat:@"%d", authorizationStatus] forKey:@"FAILURE REASON"];
    NSError *requestFailure = [[NSError alloc] initWithDomain:@"TTGeoWrapper" code:0 userInfo:requestFailureUserInfo];
    [_delegate requestDidFail:requestFailure TTGeoWrapper:self];*/
}

-(void)stopMonitoringSignificantChanges
{
    [locationManager stopMonitoringSignificantLocationChanges];
}

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
//per Apple documentation, the last item in the array is the most current location
        //http://developer.apple.com/library/ios/#documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/CLLocationManagerDelegate/CLLocationManagerDelegate.html
    int latestPollIndex = locations.count-1;
    CLLocation *location = [locations objectAtIndex:latestPollIndex];
    _timeStamp = location.timestamp;
    CLLocationCoordinate2D coordinate = [location coordinate];
    [self updateLocationWithLatAsync:coordinate.latitude Long:coordinate.longitude];
}

-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:    (CLAuthorizationStatus)status
{
    if (status != kCLAuthorizationStatusAuthorized) {
        ableToMonitorLocation = false;
    }
    authorizationStatus = status;
}

-(NSString *)updateLocationWithLatAsync:(float)latitude Long:(float)longitude;
{
    webRequest = [ASIHTTPRequest requestWithURL:[[NSURL alloc] initWithString:_URL]];
    [webRequest setDelegate:self];
    [webRequest setTimeOutSeconds:_transactionTimeout];
    [self buildPacketLat:latitude Long:longitude];
    PostGUID = [self generateUuidString];
    [self getPostResponseAsync];
    return PostGUID;
}

-(NSString *)updateLocationWithLatSync:(float)latitude Long:(float)longitude
{
    webRequest = [ASIHTTPRequest requestWithURL:[[NSURL alloc] initWithString:_URL]];
    [webRequest setDelegate:self];
    [webRequest setTimeOutSeconds:_transactionTimeout];
    [self buildPacketLat:latitude Long:longitude];
    PostGUID = [self generateUuidString];
    [self getPostResponse];
    return PostGUID;
}

-(void)buildPacketLat:(float)latitude Long:(float)longitude
{
//removed code
    [webRequest appendPostData:[requestXML dataUsingEncoding:NSASCIIStringEncoding]];
}

- (NSString *)generateUuidString
{
    CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
    CFStringRef str = CFUUIDCreateString(kCFAllocatorDefault, uuid);
    NSString *uuidString = (__bridge NSString *)str;
    CFRelease(uuid);
    CFRelease(str);
    return uuidString;
}

-(void)getPostResponse
{
    NSLog(@"Beginning Synchronous POST");
    [webRequest startSynchronous];
}

-(void)getPostResponseAsync
{
    NSLog(@"Beginning Asynchronous POST");
    [webRequest startAsynchronous];
}

-(void)cancelAsyncRequest
{
    NSLog(@"Cancelling Asynchronous POST");
    [webRequest cancel];
}

-(void)requestFinished:(ASIHTTPRequest *)request
{
    OpenXML *geoResponse = [[OpenXML alloc] initWithData:[request responseData]];
    _LocationToXMLString = [geoResponse openXMLToString];
    _LocationToOpenXML = geoResponse;
//removed code
else
{
    NSMutableDictionary *requestFailureUserInfo = [[NSMutableDictionary alloc] init];
    //removed code
    NSError *requestFailure = [[NSError alloc] initWithDomain:@"TTGeoWrapper" code:0 userInfo:requestFailureUserInfo];
    [_delegate requestDidFail:requestFailure TTGeoWrapper:self];
}
}

-(void)requestFailed:(ASIHTTPRequest *)request
{
    NSError *requestFailure = [request error];
    [_delegate requestDidFail:requestFailure TTGeoWrapper:self];
}
@end

Apparently, this works only if you re-init CLLocationManager each time too. The documentation does not seem to support that, but my testing certainly does. If someone has a better answer, I would love to hear it.


You are right. Only a re-init of the CLLocationManager will cause the SignificantLocationChanges update for to occur. If you need a fresh location update, then why not use standard location service? Using the standard you also get a much more accurate fix.

链接地址: http://www.djcxy.com/p/20350.html

上一篇: 如何使用CoreLocation在后台退出区域时重置区域中心

下一篇: CLLocationManager SignificantLocationChanges强制刷新