diff --git a/MTLocateMe.h b/MTLocateMe.h index 3c3a02d..4577eb4 100644 --- a/MTLocateMe.h +++ b/MTLocateMe.h @@ -17,3 +17,4 @@ #import "MTLocateMeButton.h" #import "MTLocationDefines.h" #import "MTLocationFunctions.h" +#import "MTLocationManager.h" diff --git a/MTLocateMeBarButtonItem.h b/MTLocateMeBarButtonItem.h index 8e506c2..66bb47f 100644 --- a/MTLocateMeBarButtonItem.h +++ b/MTLocateMeBarButtonItem.h @@ -17,21 +17,19 @@ #import "MTLocationDefines.h" @class MTLocateMeButton; +@protocol MTLocateMeButtonDelegate; -@interface MTLocateMeBarButtonItem : UIBarButtonItem { +@interface MTLocateMeBarButtonItem : UIBarButtonItem { MTLocateMeButton *locateMeButton_; - CLLocationManager *locationManager_; } @property (nonatomic, assign) MTLocationStatus locationStatus; @property (nonatomic, assign) BOOL headingEnabled; -@property (nonatomic, readonly) CLLocationManager *locationManager; +@property (nonatomic, assign) id delegate; - (id)initWithLocationStatus:(MTLocationStatus)locationStatus; -// if you pass in a locationManager the button acts as it's delegate and sends Notifications when location changes -- (id)initWithLocationStatus:(MTLocationStatus)locationStatus locationManager:(CLLocationManager *)locationManager; - (void)setLocationStatus:(MTLocationStatus)locationStatus animated:(BOOL)animated; diff --git a/MTLocateMeBarButtonItem.m b/MTLocateMeBarButtonItem.m index 5709352..c5e2287 100644 --- a/MTLocateMeBarButtonItem.m +++ b/MTLocateMeBarButtonItem.m @@ -25,6 +25,10 @@ @interface MTLocateMeBarButtonItem () @property (nonatomic, retain) MTLocateMeButton *locateMeButton; +- (void)locationManagerDidUpdateToLocationFromLocation:(NSNotification *)notification; +- (void)locationManagerDidUpdateHeading:(NSNotification *)notification; +- (void)locationManagerDidFail:(NSNotification *)notification; + @end @@ -32,7 +36,6 @@ @implementation MTLocateMeBarButtonItem @synthesize locateMeButton = locateMeButton_; @synthesize headingEnabled = headingEnabled_; -@synthesize locationManager = locationManager_; //////////////////////////////////////////////////////////////////////// @@ -41,33 +44,43 @@ @implementation MTLocateMeBarButtonItem //////////////////////////////////////////////////////////////////////// // the designated initializer -- (id)initWithLocationStatus:(MTLocationStatus)locationStatus locationManager:(CLLocationManager *)locationManager { +- (id)initWithLocationStatus:(MTLocationStatus)locationStatus { locateMeButton_ = [[MTLocateMeButton alloc] initWithFrame:CGRectZero]; - + if ((self = [super initWithCustomView:locateMeButton_])) { locateMeButton_.locationStatus = locationStatus; - locateMeButton_.locationManager = locationManager; - // pass is nil for locationManager if you don't want to use it - locationManager_ = [locationManager retain]; - locationManager_.delegate = self; + + // begin listening to location update notifications + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(locationManagerDidUpdateToLocationFromLocation:) + name:kMTLocationManagerDidUpdateToLocationFromLocation + object:nil]; + // begin listening to heading update notifications + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(locationManagerDidUpdateHeading:) + name:kMTLocationManagerDidUpdateHeading + object:nil]; + // begin listening to heading update notifications + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(locationManagerDidFail:) + name:kMTLocationManagerDidFailWithError + object:nil]; } - + return self; } -- (id)initWithLocationStatus:(MTLocationStatus)locationStatus { - return [self initWithLocationStatus:locationStatus locationManager:nil]; -} - // The designated initializer of the base-class - (id)initWithCustomView:(UIView *)customView { return [self initWithLocationStatus:MTLocationStatusIdle]; } - (void)dealloc { + // end listening to location update notifications + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [locateMeButton_ release], locateMeButton_ = nil; - [locationManager_ release], locationManager_ = nil; - + [super dealloc]; } @@ -100,17 +113,25 @@ - (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvent [self.locateMeButton addTarget:target action:action forControlEvents:controlEvents]; } +- (void)setDelegate:(id)delegate { + self.locateMeButton.delegate = delegate; +} + +- (id)delegate { + return self.locateMeButton.delegate; +} + + //////////////////////////////////////////////////////////////////////// #pragma mark - -#pragma mark locationManager Delegate +#pragma mark Location Manager Notifications //////////////////////////////////////////////////////////////////////// -- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { - NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", - newLocation, @"newLocation", - oldLocation, @"oldLocation", nil]; - // only set new location status if we are currently not receiving heading updates +- (void)locationManagerDidUpdateToLocationFromLocation:(NSNotification *)notification { + CLLocation *newLocation = [notification.userInfo valueForKey:@"newLocation"]; + + // only set new location status if we are currently not receiving heading updates if (self.locationStatus != MTLocationStatusReceivingHeadingUpdates) { // if horizontal accuracy is below our threshold update status if (newLocation.horizontalAccuracy < kMTLocationMinimumHorizontalAccuracy) { @@ -119,59 +140,20 @@ - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLoca [self setLocationStatus:MTLocationStatusSearching animated:YES]; } } - - [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerDidUpdateToLocationFromLocation object:self userInfo:userInfo]; -} - -- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { - NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", - error, @"error", nil]; - - [self setLocationStatus:MTLocationStatusIdle animated:YES]; - - [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerDidFailWithError object:self userInfo:userInfo]; -} - -- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading { - NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", - newHeading, @"newHeading", nil]; - - [self setLocationStatus:MTLocationStatusReceivingHeadingUpdates animated:YES]; - - [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerDidUpdateHeading object:self userInfo:userInfo]; -} - -- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager { - return YES; } -- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { - NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", - region, @"region", nil]; - - [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerDidEnterRegion object:self userInfo:userInfo]; -} - -- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { - NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", - region, @"region", nil]; - - [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerDidExitRegion object:self userInfo:userInfo]; +- (void)locationManagerDidUpdateHeading:(NSNotification *)notification { + CLHeading *newHeading = [notification.userInfo valueForKey:@"newHeading"]; + + if (newHeading.headingAccuracy > 0) { + [self setLocationStatus:MTLocationStatusReceivingHeadingUpdates animated:YES]; + } else { + [self setLocationStatus:MTLocationStatusReceivingLocationUpdates animated:YES]; + } } -- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error { - NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", - region, @"region", - error, @"error", nil]; - - [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerMonitoringDidFailForRegion object:self userInfo:userInfo]; -} - -- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { - NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", - [NSNumber numberWithInt:status], @"status", nil]; - - [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerDidChangeAuthorizationStatus object:self userInfo:userInfo]; +- (void)locationManagerDidFail:(NSNotification *)notification { + [self setLocationStatus:MTLocationStatusIdle animated:YES]; } diff --git a/MTLocateMeBarButtonItem.xcodeproj/project.pbxproj b/MTLocateMeBarButtonItem.xcodeproj/project.pbxproj index 8e6e635..d5546d3 100644 --- a/MTLocateMeBarButtonItem.xcodeproj/project.pbxproj +++ b/MTLocateMeBarButtonItem.xcodeproj/project.pbxproj @@ -16,6 +16,8 @@ 39CFA14312FA267100B859F9 /* MTLocationFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 39CFA14112FA267100B859F9 /* MTLocationFunctions.h */; }; 39CFA14412FA267100B859F9 /* MTLocationFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 39CFA14212FA267100B859F9 /* MTLocationFunctions.m */; }; 39CFA15E12FA29F000B859F9 /* MTLocateMe.h in Headers */ = {isa = PBXBuildFile; fileRef = 39CFA15D12FA29F000B859F9 /* MTLocateMe.h */; }; + 39E47D1312FF41D100649F01 /* MTLocationManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 39E47D1112FF41D100649F01 /* MTLocationManager.h */; }; + 39E47D1412FF41D100649F01 /* MTLocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 39E47D1212FF41D100649F01 /* MTLocationManager.m */; }; AA747D9F0F9514B9006C5449 /* MTLocateMeBarButtonItem_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = AA747D9E0F9514B9006C5449 /* MTLocateMeBarButtonItem_Prefix.pch */; }; AACBBE4A0F95108600F1A2B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACBBE490F95108600F1A2B1 /* Foundation.framework */; }; /* End PBXBuildFile section */ @@ -38,6 +40,8 @@ 39CFA14112FA267100B859F9 /* MTLocationFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTLocationFunctions.h; sourceTree = ""; }; 39CFA14212FA267100B859F9 /* MTLocationFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MTLocationFunctions.m; sourceTree = ""; }; 39CFA15D12FA29F000B859F9 /* MTLocateMe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTLocateMe.h; sourceTree = ""; }; + 39E47D1112FF41D100649F01 /* MTLocationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTLocationManager.h; sourceTree = ""; }; + 39E47D1212FF41D100649F01 /* MTLocationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MTLocationManager.m; sourceTree = ""; }; AA747D9E0F9514B9006C5449 /* MTLocateMeBarButtonItem_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTLocateMeBarButtonItem_Prefix.pch; sourceTree = SOURCE_ROOT; }; AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; D2AAC07E0554694100DB518D /* libMTLocateMeBarButtonItem.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMTLocateMeBarButtonItem.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -88,6 +92,7 @@ 08FB77AEFE84172EC02AAC07 /* Classes */ = { isa = PBXGroup; children = ( + 39E47D1012FF41A000649F01 /* Delegation */, 39CFA14712FA268F00B859F9 /* Buttons */, 39CFA14612FA268500B859F9 /* Utils */, 39CFA15D12FA29F000B859F9 /* MTLocateMe.h */, @@ -139,6 +144,15 @@ name = Buttons; sourceTree = ""; }; + 39E47D1012FF41A000649F01 /* Delegation */ = { + isa = PBXGroup; + children = ( + 39E47D1112FF41D100649F01 /* MTLocationManager.h */, + 39E47D1212FF41D100649F01 /* MTLocationManager.m */, + ); + name = Delegation; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -152,6 +166,7 @@ 39382D7E12E9B6400012007D /* MTLocationDefines.h in Headers */, 39CFA14312FA267100B859F9 /* MTLocationFunctions.h in Headers */, 39CFA15E12FA29F000B859F9 /* MTLocateMe.h in Headers */, + 39E47D1312FF41D100649F01 /* MTLocationManager.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -208,6 +223,7 @@ 39382D7B12E9B6400012007D /* MTLocateMeBarButtonItem.m in Sources */, 39382D7D12E9B6400012007D /* MTLocateMeButton.m in Sources */, 39CFA14412FA267100B859F9 /* MTLocationFunctions.m in Sources */, + 39E47D1412FF41D100649F01 /* MTLocationManager.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MTLocateMeButton.h b/MTLocateMeButton.h index 6ec57ae..de1d503 100644 --- a/MTLocateMeButton.h +++ b/MTLocateMeButton.h @@ -16,6 +16,8 @@ #import #import "MTLocationDefines.h" +@protocol MTLocateMeButtonDelegate; + @interface MTLocateMeButton : UIButton { // Current Location-State of the Button @@ -34,13 +36,23 @@ UIView *activeSubview_; BOOL headingEnabled_; - CLLocationManager *locationManager_; + + id delegate_; } @property (nonatomic, assign) MTLocationStatus locationStatus; @property (nonatomic, assign) BOOL headingEnabled; @property (nonatomic, retain) CLLocationManager *locationManager; +@property (nonatomic, assign) id delegate; - (void)setLocationStatus:(MTLocationStatus)locationStatus animated:(BOOL)animated; @end + + + +@protocol MTLocateMeButtonDelegate + +- (void)locateMeButton:(MTLocateMeButton *)locateMeButton didChangeLocationStatus:(MTLocationStatus)locationStatus; + +@end \ No newline at end of file diff --git a/MTLocateMeButton.m b/MTLocateMeButton.m index 9fe5def..b9985e0 100644 --- a/MTLocateMeButton.m +++ b/MTLocateMeButton.m @@ -75,6 +75,7 @@ @implementation MTLocateMeButton @synthesize imageViewFrame = imageViewFrame_; @synthesize activeSubview = activeSubview_; @synthesize locationManager = locationManager_; +@synthesize delegate = delegate_; //////////////////////////////////////////////////////////////////////// @@ -114,6 +115,7 @@ - (id)initWithFrame:(CGRect)frame { } - (void)dealloc { + delegate_ = nil; [activityIndicator_ release], activityIndicator_ = nil; [imageView_ release], imageView_ = nil; [locationManager_ release], locationManager_ = nil; @@ -261,38 +263,8 @@ - (void)locationStatusToggled:(id)sender { // update to new location status [self setLocationStatus:newLocationStatus animated:YES]; - // check new status after status-toggle - // and update locationManager accordingly - switch(newLocationStatus) { - // if we are currently idle, stop updates - case MTLocationStatusIdle: - //NSLog(@"Stopped updating"); - [self.locationManager stopUpdatingLocation]; - [self.locationManager stopUpdatingHeading]; - break; - - // if we are currently searching, start updating location - case MTLocationStatusSearching: - //NSLog(@"Start updating location"); - [self.locationManager startUpdatingLocation]; - [self.locationManager stopUpdatingHeading]; - break; - - // if we are already receiving updates - case MTLocationStatusReceivingLocationUpdates: - //NSLog(@"Start updating location"); - [self.locationManager startUpdatingLocation]; - [self.locationManager stopUpdatingHeading]; - break; - - // if we are currently receiving heading updates, start updating heading - case MTLocationStatusReceivingHeadingUpdates: - //NSLog(@"start updating heading"); - [self.locationManager startUpdatingLocation]; - [self.locationManager startUpdatingHeading]; - break; - - } + // call delegate + [self.delegate locateMeButton:self didChangeLocationStatus:newLocationStatus]; } // sets a view to a smaller frame, used for animation diff --git a/MTLocationManager.h b/MTLocationManager.h new file mode 100644 index 0000000..b600d74 --- /dev/null +++ b/MTLocationManager.h @@ -0,0 +1,43 @@ +// +// MTLocationManager.h +// +// Created by Matthias Tretter on 06.02.11. +// Copyright (c) 2009-2011 Matthias Tretter, @myell0w. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#import +#import +#import "MTLocateMeButton.h" +#import "MTLocateMeBarButtonItem.h" + +// Singleton class that acts as the Location Manager and it's delegate +// Sends Notifications when CLLocationManagerDelegate-Methods are called +@interface MTLocationManager : NSObject { + // The Core Location location manager + CLLocationManager *locationManager_; +} + + +//////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Properties +//////////////////////////////////////////////////////////////////////// + +@property (nonatomic, retain) CLLocationManager *locationManager; + +//////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Class Methods +//////////////////////////////////////////////////////////////////////// + +// Singleton Instance ++ (MTLocationManager *)sharedInstance; + +@end diff --git a/MTLocationManager.m b/MTLocationManager.m new file mode 100644 index 0000000..4d26eb8 --- /dev/null +++ b/MTLocationManager.m @@ -0,0 +1,198 @@ +// +// MTLocationManager.m +// +// Created by Matthias Tretter on 06.02.11. +// Copyright (c) 2009-2011 Matthias Tretter, @myell0w. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#import "MTLocationManager.h" +#import "MTLocationDefines.h" + + +@implementation MTLocationManager + +@synthesize locationManager = locationManager_; + + +//////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Lifecycle +//////////////////////////////////////////////////////////////////////// + + +- (id)init { + if ((self = [super init])) { + locationManager_ = [[CLLocationManager alloc] init]; + locationManager_.delegate = self; + } + + return self; +} + +- (void)dealloc { + [locationManager_ release], locationManager_ = nil; + + [super dealloc]; +} + + + +//////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark locationManager Delegate +//////////////////////////////////////////////////////////////////////// + + +- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", + newLocation, @"newLocation", + oldLocation, @"oldLocation", nil]; + + [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerDidUpdateToLocationFromLocation object:self userInfo:userInfo]; +} + +- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", + error, @"error", nil]; + + [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerDidFailWithError object:self userInfo:userInfo]; +} + +- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading { + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", + newHeading, @"newHeading", nil]; + + [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerDidUpdateHeading object:self userInfo:userInfo]; +} + +- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager { + return YES; +} + +- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", + region, @"region", nil]; + + [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerDidEnterRegion object:self userInfo:userInfo]; +} + +- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", + region, @"region", nil]; + + [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerDidExitRegion object:self userInfo:userInfo]; +} + +- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error { + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", + region, @"region", + error, @"error", nil]; + + [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerMonitoringDidFailForRegion object:self userInfo:userInfo]; +} + +- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: manager, @"locationManager", + [NSNumber numberWithInt:status], @"status", nil]; + + [[NSNotificationCenter defaultCenter] postNotificationName:kMTLocationManagerDidChangeAuthorizationStatus object:self userInfo:userInfo]; +} + + +//////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark MTLocateMeButtonDelegate Methods +//////////////////////////////////////////////////////////////////////// + +- (void)locateMeButton:(MTLocateMeButton *)locateMeButton didChangeLocationStatus:(MTLocationStatus)locationStatus { + // check new status after status-toggle and update locationManager accordingly + switch(locationStatus) { + // if we are currently idle, stop updates + case MTLocationStatusIdle: + //NSLog(@"Stopped updating"); + [self.locationManager stopUpdatingLocation]; + [self.locationManager stopUpdatingHeading]; + break; + + // if we are currently searching, start updating location + case MTLocationStatusSearching: + //NSLog(@"Start updating location"); + [self.locationManager startUpdatingLocation]; + [self.locationManager stopUpdatingHeading]; + break; + + // if we are already receiving updates + case MTLocationStatusReceivingLocationUpdates: + //NSLog(@"Start updating location"); + [self.locationManager startUpdatingLocation]; + [self.locationManager stopUpdatingHeading]; + break; + + // if we are currently receiving heading updates, start updating heading + case MTLocationStatusReceivingHeadingUpdates: + //NSLog(@"start updating heading"); + [self.locationManager startUpdatingLocation]; + [self.locationManager startUpdatingHeading]; + break; + + } +} + + +//////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Singleton definitons +//////////////////////////////////////////////////////////////////////// + +static MTLocationManager *sharedMTLocationManager = nil; + ++ (MTLocationManager *)sharedInstance { + @synchronized(self) { + if (sharedMTLocationManager == nil) { + sharedMTLocationManager = [[self alloc] init]; + } + } + + return sharedMTLocationManager; +} + ++ (id)allocWithZone:(NSZone *)zone { + @synchronized(self) { + if (sharedMTLocationManager == nil) { + sharedMTLocationManager = [super allocWithZone:zone]; + + return sharedMTLocationManager; + } + } + + return nil; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (id)retain { + return self; +} + +- (NSUInteger)retainCount { + return NSUIntegerMax; +} + +- (void)release { +} + +- (id)autorelease { + return self; +} + +@end diff --git a/Readme.mdown b/Readme.mdown index 56989ec..2ae1fd3 100644 --- a/Readme.mdown +++ b/Readme.mdown @@ -6,10 +6,11 @@ Read Me Description ----------------- -This class mimics the LocateMe-Button of the built-in Google Maps App on iOS. -It's either a drop-in-replacement for any BarButtonItem you may have used until now, or can optionally act as the LocationManagerDelegate for you and send Notification whenever a delegate-method gets called. The switch from one mode to another is animated, just like in the Google Maps App. +These classes aim to mimic some of the functions of the built-in Google Maps App on iOS for you. +Currently the library contains a simple Location Manager-Singleton that sends out notifications when CLLocationManager-Delegate-Methods are called and a UIBarButtonItem/UIButton that acts as a Locate-Me Button that behaves similar to the one in the Google Maps App. +The switch from one mode to another is animated, just like in the Google Maps App. -It can also be customized to support Heading-Mode or not, by setting property headingEnabled. +It can also be customized to support Heading-Updates or not, by setting property headingEnabled. Installation ------------------ @@ -22,8 +23,15 @@ Usage You can use MTLocateMeBarButtonItem like this: + // Configure Location Manager + [MTLocationManager sharedInstance].locationManager.desiredAccuracy = kCLLocationAccuracyBest; + [MTLocationManager sharedInstance].locationManager.distanceFilter = kCLDistanceFilterNone; + [MTLocationManager sharedInstance].locationManager.headingFilter = 5; // 5 Degrees + // create locate-me item MTLocateMeBarButtonItem *locateMeItem = [[MTLocateMeBarButtonItem alloc] initWithLocationStatus:MTLocationStatusIdle]; + // set delegate that is called when mode of Button changes + locateMeItem.delegate = [MTLocationManager sharedInstance]; // add target-action [locateMeItem addTarget:self action:@selector(myCustomSelector:) forControlEvents:UIControlEventTouchUpInside]; // disable heading