MyCLController.h
#import <CoreLocation/CoreLocation.h> // This is hoping that in the future (beyond SDK 2.0) we can access SystemConfiguration info #import <SystemConfiguration/SCNetworkConnection.h> // This protocol is used to send the info for location updates back to another view controller @protocol MyCLControllerDelegate <NSObject> @required -(void)gpsUpdate:(CLLocation *)aLoc; @end // Class definition @interface MyCLController : NSObject <CLLocationManagerDelegate> { CLLocationManager *locationManager; CLLocation *myCurrentLoc; BOOL findShouldStop; id delegate; } @property (nonatomic, retain) CLLocationManager *locationManager; @property (nonatomic,assign) id <MyCLControllerDelegate> delegate; @property (nonatomic, assign) CLLocation *myCurrentLoc; - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation; - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error; + (MyCLController *)sharedInstance; @end
MyCLController.m
#import "MyCLController.h" // This is a singleton class, see below static MyCLController *sharedCLDelegate = nil; @implementation MyCLController @synthesize delegate, locationManager, myCurrentLoc; - (id) init { self = [super init]; if (self != nil) { self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; // Tells the location manager to send updates to this object self.myCurrentLoc = [[CLLocation alloc] initWithLatitude:0 longitude:0]; [self.locationManager startUpdatingLocation]; } return self; } // Called when the location is updated - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { // Horizontal coordinates if (signbit(newLocation.horizontalAccuracy)) { // Negative accuracy means an invalid or unavailable measurement [self.delegate gpsUpdate:nil]; return; } // // Altitude (we don't care about it) // if (signbit(newLocation.verticalAccuracy)) { // // Negative accuracy means an invalid or unavailable measurement // } // Check the timestamp, see if it's an hour old or more. If so, don't send an update if (ABS([newLocation.timestamp timeIntervalSinceNow]) > 3600) { [self.delegate gpsUpdate:nil]; return; } [myCurrentLoc release]; myCurrentLoc = [newLocation copy]; // TODO: Why does this increment the retain count? We should be manually retaining // Looks like the loc is good [self.delegate gpsUpdate:myCurrentLoc]; return; } // Called when there is an error getting the location // TODO: Update this function to return the proper info in the proper UI fields - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSMutableString *errorString = [[[NSMutableString alloc] init] autorelease]; BOOL shouldQuit; if ([error domain] == kCLErrorDomain) { // We handle CoreLocation-related errors here switch ([error code]) { // This error code is usually returned whenever user taps "Don't Allow" in response to // being told your app wants to access the current location. Once this happens, you cannot // attempt to get the location again until the app has quit and relaunched. // // "Don't Allow" on two successive app launches is the same as saying "never allow". The user // can reset this for all apps by going to Settings > General > Reset > Reset Location Warnings. // case kCLErrorDenied: [errorString appendFormat:@"%@\n", NSLocalizedString(@"LocationDenied", nil)]; [errorString appendFormat:@"%@\n", NSLocalizedString(@"AppWillQuit", nil)]; shouldQuit = YES; break; // This error code is usually returned whenever the device has no data or WiFi connectivity, // or when the location cannot be determined for some other reason. // // CoreLocation will keep trying, so you can keep waiting, or prompt the user. // case kCLErrorLocationUnknown: [errorString appendFormat:@"%@\n", NSLocalizedString(@"LocationUnknown", nil)]; [errorString appendFormat:@"%@\n", NSLocalizedString(@"AppWillQuit", nil)]; shouldQuit = YES; break; // We shouldn't ever get an unknown error code, but just in case... // default: [errorString appendFormat:@"%@ %d\n", NSLocalizedString(@"GenericLocationError", nil), [error code]]; shouldQuit = NO; break; } } else { // We handle all non-CoreLocation errors here // (we depend on localizedDescription for localization) [errorString appendFormat:@"Error domain: \"%@\" Error code: %d\n", [error domain], [error code]]; [errorString appendFormat:@"Description: \"%@\"\n", [error localizedDescription]]; shouldQuit = NO; } // TODO: Send the delegate the alert? if (shouldQuit) { // do nothing } } #pragma mark ---- singleton object methods ---- // See "Creating a Singleton Instance" in the Cocoa Fundamentals Guide for more info + (MyCLController *)sharedInstance { @synchronized(self) { if (sharedCLDelegate == nil) { [[self alloc] init]; // assignment not done here } } return sharedCLDelegate; } + (id)allocWithZone:(NSZone *)zone { @synchronized(self) { if (sharedCLDelegate == nil) { sharedCLDelegate = [super allocWithZone:zone]; return sharedCLDelegate; // assignment and return on first allocation } } return nil; // on subsequent allocation attempts return nil } - (id)copyWithZone:(NSZone *)zone { return self; } - (id)retain { return self; } - (unsigned)retainCount { return UINT_MAX; // denotes an object that cannot be released } - (void)release { //do nothing } - (id)autorelease { return self; } @end
在用MKReverseGeocoder的时候是不是经常crash呀,那是因为在同一时刻只能存在一个MKReverseGeocoder实例。
参考资料:
http://evilrockhopper.com/2010/01/iphone-development-reverse-geocoding/