使用CLLocationManager的自定义位置管理器类

时间:2013-01-11 08:44:17

标签: iphone ios design-patterns cllocationmanager cocoa-design-patterns

我对iOS开发(我的第一个应用程序)很陌生,我遇到了这个问题。

我有一个iPhone应用程序,应该在用户按钮触摸时获得用户在多个ViewControllers中的当前位置。为了防止冗余代码(在不同的视图控制器中多次实现locationManager:didFailWithErrorlocationManager:didUpdateToLocation:fromLocation等),我决定创建一个名为LocationManager的自定义类:

LocationManager.h

@interface LocationManager : NSObject <CLLocationManagerDelegate> {
@private
    CLLocationManager *CLLocationManagerInstance;
    id<LocationManagerAssigneeProtocol> assignee;
}

-(void) getUserLocationWithDelegate:(id) delegate;

LocationManager.m

@implementation LocationManager

-(id)init {
    self = [super init];
    if(self) {
        CLLocationManagerInstance = [[CLLocationManager alloc] init];
        CLLocationManagerInstance.desiredAccuracy = kCLLocationAccuracyBest;
        CLLocationManagerInstance.delegate = self;
    }
    return self;
}

-(void) getUserLocationWithDelegate:(id) delegate {
    if([CLLocationManager locationServicesEnabled]) {
        assignee = delegate;
        [CLLocationManagerInstance startUpdatingLocation];
    }
}

#pragma CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
...
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    [CLLocationManagerInstance stopUpdatingLocation];
    [assignee didUpdateToLocation:newLocation];
}

我有一个名为 LocationManagerAssigneeProtocol 的协议,我的ViewControllers实现了

@protocol LocationManagerAssigneeProtocol <NSObject>

@required
-(void) didUpdateToLocation:(CLLocation *) location;

@end

并在我的viewcontroller中需要

- (IBAction)getMyLocation:(id)sender {

    [locationMgr getUserLocationWithDelegate:self];
}

这段代码完美无缺,然而,我感觉我在这里违反了一些设计模式,让LocationManager能够调用自己发起对位置管理器调用的类的功能。另一方面,我不想为所有应该使用位置的视图控制器实现 CLLocationManagerDelegate

这个问题有更好的解决方案吗?

1 个答案:

答案 0 :(得分:2)

我同意@CarlVeazey对此的看法。 Delegate非常适合任何时候存在的1对1关系,但在您的情况下,您可能需要多个viewControllers来响应任何给定时间的位置事件。因此,只需删除与您的委托及其相关协议相关的任何内容。

我可能会将LocationManager类设为单例并修改更新方法:

+(LocationManager *)sharedInstance
{
    static LocationManager *_sharedInstance = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _sharedInstance = [[self alloc] init];
    });

    return _sharedInstance;
}

-(void)getUserLocation
{
    if ([CLLocationManager locationServicesEnabled])
        [CLLocationManager startUpdatingLocation];
}

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{
    [CLLocationManagerInstance stopUpdatingLocation];
    [[NSNotificationCenter defaultCenter] postNotificationWithName:@"LocationManagerDidUpdateLocation" object:newLocation];
}

...然后任何需要使用此类的viewController都会有:

-(void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserverForName:@"LocationManagerDidUpdateLocation" object:self queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
        CLLocation *location = note.object;
        ...
    }];
}

-(IBAction)getMyLocation:(id)sender {
    [[LocationManager sharedInstance] getUserLocation];
}

希望这有帮助并且有意义。