diff options
author | matthew <matthew> | 2008-10-02 16:32:27 +0000 |
---|---|---|
committer | matthew <matthew> | 2008-10-02 16:32:27 +0000 |
commit | 1e276f5555ca52c43b62954327cc44f40b8b0f58 (patch) | |
tree | df3b7807016ace0e1e0d3e781fba3cf287324a4d /iphone/FixMyStreet/MyCLController.m | |
parent | 37f57cc8b8332ba5a19e39657d388d3cc7a5b656 (diff) |
Initial revision
Diffstat (limited to 'iphone/FixMyStreet/MyCLController.m')
-rwxr-xr-x | iphone/FixMyStreet/MyCLController.m | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/iphone/FixMyStreet/MyCLController.m b/iphone/FixMyStreet/MyCLController.m new file mode 100755 index 000000000..d289d6ade --- /dev/null +++ b/iphone/FixMyStreet/MyCLController.m @@ -0,0 +1,232 @@ +/* + +File: MyCLController.m +Abstract: Singleton class used to talk to CoreLocation and send results back to +the app's view controllers. + +Version: 1.1 + +Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. +("Apple") in consideration of your agreement to the following terms, and your +use, installation, modification or redistribution of this Apple software +constitutes acceptance of these terms. If you do not agree with these terms, +please do not use, install, modify or redistribute this Apple software. + +In consideration of your agreement to abide by the following terms, and subject +to these terms, Apple grants you a personal, non-exclusive license, under +Apple's copyrights in this original Apple software (the "Apple Software"), to +use, reproduce, modify and redistribute the Apple Software, with or without +modifications, in source and/or binary forms; provided that if you redistribute +the Apple Software in its entirety and without modifications, you must retain +this notice and the following text and disclaimers in all such redistributions +of the Apple Software. +Neither the name, trademarks, service marks or logos of Apple Inc. may be used +to endorse or promote products derived from the Apple Software without specific +prior written permission from Apple. Except as expressly stated in this notice, +no other rights or licenses, express or implied, are granted by Apple herein, +including but not limited to any patent rights that may be infringed by your +derivative works or by other works in which the Apple Software may be +incorporated. + +The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO +WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED +WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN +COMBINATION WITH YOUR PRODUCTS. + +IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR +DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF +CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Copyright (C) 2008 Apple Inc. All Rights Reserved. + +*/ + +#import "MyCLController.h" + +// This is a singleton class, see below +static MyCLController *sharedCLDelegate = nil; + +@implementation MyCLController + +@synthesize delegate, locationManager, updating; + +- (id) init { + self = [super init]; + if (self != nil) { + self.locationManager = [[[CLLocationManager alloc] init] autorelease]; + self.locationManager.delegate = self; // Tells the location manager to send updates to this object + } + return self; +} + +-(void)startUpdatingLocation { + self.updating = YES; + [self.locationManager startUpdatingLocation]; +} + + +// Called when the location is updated +- (void)locationManager:(CLLocationManager *)manager + didUpdateToLocation:(CLLocation *)newLocation + fromLocation:(CLLocation *)oldLocation +{ + NSMutableString *update = [[[NSMutableString alloc] init] autorelease]; + + // Timestamp + NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease]; + [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; + [dateFormatter setTimeStyle:NSDateFormatterMediumStyle]; + [update appendFormat:@"%@\n\n", [dateFormatter stringFromDate:newLocation.timestamp]]; + + // Horizontal coordinates + if (signbit(newLocation.horizontalAccuracy)) { + // Negative accuracy means an invalid or unavailable measurement + [update appendString:@"Latitude / Longitude unavailable"]; + } else { + // CoreLocation returns positive for North & East, negative for South & West + [update appendFormat:@"Location: %.4f° %@, %.4f° %@", // This format takes 4 args: 2 pairs of the form coordinate + compass direction + fabs(newLocation.coordinate.latitude), signbit(newLocation.coordinate.latitude) ? (@"South") : (@"North"), + fabs(newLocation.coordinate.longitude), signbit(newLocation.coordinate.longitude) ? (@"West") : (@"East")]; + [update appendString:@"\n"]; + [update appendFormat:@"(accuracy %.0f metres)", newLocation.horizontalAccuracy]; + } + [update appendString:@"\n\n"]; + + // Altitude + if (signbit(newLocation.verticalAccuracy)) { + // Negative accuracy means an invalid or unavailable measurement + [update appendString:@"Altitude Unavailable"]; + } else { + // Positive and negative in altitude denote above & below sea level, respectively + [update appendFormat:@"Altitude: %.2f metres %@", fabs(newLocation.altitude), (signbit(newLocation.altitude)) ? @"below sea level" : @"above sea level"]; + [update appendString:@"\n"]; + [update appendFormat:@"(accuracy %.0f metres)", newLocation.verticalAccuracy]; + } + [update appendString:@"\n\n"]; + + // Calculate disatance moved and time elapsed, but only if we have an "old" location + // + // NOTE: Timestamps are based on when queries start, not when they return. CoreLocation will query your + // location based on several methods. Sometimes, queries can come back in a different order from which + // they were placed, which means the timestamp on the "old" location can sometimes be newer than on the + // "new" location. For the example, we will clamp the timeElapsed to zero to avoid showing negative times + // in the UI. + // + if (oldLocation != nil) { + CLLocationDistance distanceMoved = [newLocation getDistanceFrom:oldLocation]; + NSTimeInterval timeElapsed = [newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp]; + + [update appendFormat:@"Location changed %.2f metres ", distanceMoved]; + if (signbit(timeElapsed)) { + [update appendString:@"since previous measurement"]; + } else { + [update appendFormat:@"in %.1f seconds", timeElapsed]; + } + [update appendString:@"\n\n"]; + } + + // Send the update to our delegate + [self.delegate newLocationUpdate:update]; +} + + +// Called when there is an error getting the location +- (void)locationManager:(CLLocationManager *)manager + didFailWithError:(NSError *)error +{ + NSMutableString *errorString = [[[NSMutableString alloc] init] autorelease]; + + 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)]; + 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)]; + break; + + // We shouldn't ever get an unknown error code, but just in case... + // + default: + [errorString appendFormat:@"%@ %d\n", NSLocalizedString(@"GenericLocationError", nil), [error code]]; + 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]]; + } + + self.updating = NO; + + // Send the update to our delegate + [self.delegate newLocationUpdate:errorString]; +} + +#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
\ No newline at end of file |