2011-04-13 24 views
0

我想获取用户的多个控制器上的当前位置,他们是导航控制器,tabbarcontroller,presentmodel控制器的一部分,所以基本上我真的不能做像self.navigationcontroller或self.tabBarController 。iPhone需要更新位置在多个控制器

我做什么我创建了一个LocationHelper和LocationHelperDelegate

@protocol LocationHelperDelegate 
@required 
- (void)locationUpdate:(CLLocation *)location; // Our location updates are sent here 
- (void)locationError:(NSError *)error; // Any errors are sent here 
@end 

@interface LocationHelper : NSObject <CLLocationManagerDelegate>{ 
CLLocationManager *locationManager; 
CLLocation *currentLocation; 
id delegate; 
} 

@property (nonatomic, retain) CLLocation *currentLocation; 
@property (nonatomic, retain) CLLocationManager *locationManager; 
@property (nonatomic, assign) id delegate; 
@end 

然后在我的.m文件我下面

-(id) init { 
    self = [super init]; 
    if(self != nil){ 
     self.locationManager = [[[CLLocationManager alloc] init] autorelease]; 
     self.locationManager.delegate = self; 
    } 
    return self; 
} 

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation  
    *)newLocation fromLocation:(CLLocation *)oldLocation { 
    if([self.delegate conformsToProtocol:@protocol(LocationHelperDelegate)]) { 
     [self.delegate locationUpdate:newLocation]; 
    } 
    } 

然后现在这是我在我做我需要位置更新的所有控制器。 在init方法

LocationHelper* locationHelper = [[LocationHelper alloc]init]; 
locationHelper.delegate = self; 
[locationHelper.locationManager startUpdatingLocation]; 

,然后我实现

- (void)locationUpdate:(CLLocation *)location { 
    latitude = location.coordinate.latitude; 
    longitude = location.coordinate.longitude; 
    [locationHelper.locationManager stopUpdatingLocation]; 
} 

我100%肯定这是不是做正确的方式,但我不知道我应该怎么做这个。基本上我只需要做一次startUpdatingLocation,然后我的所有控制器都会得到locationUpdate的通知,并且每个控制器都收到通知stopUpdatingLocation。

我在考虑让LocationHelper类有一个singleton,但是当所有控制器都获得它的实例时,他们可以将它们设置为委托自己,这似乎不对,因为委托是实例变量之一LocationHelper,它只能保存一个值。

所以,你可以看到我很困惑,请帮助。

回答

4

我走上了追赶使用NSNotificationCenter从一个多线程的网络请求响应的方法。这是令人难以置信的容易实现,并不需要你在一个特定的地方保存一个变量,如AppDelegate。如果您决定稍后重构代码,这显然会使事情更加灵活。

要发送通知,您可以使用这样的代码。请注意,我们使用userInfo:paramater传递自定义数据。

[[NSNotificationCenter defaultCenter] postNotificationName:@"requestFinished" 
                object:self 
                userInfo:resultDictionary]; 

要订阅通知上述通知,请使用下面的代码。不是名称:与上面的postNotificationName匹配。根据您的需要,您可以如何分派和订阅多个通知。

[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(requestFinishedHandler:) 
              name:@"requestFinished" 
              object:nil]; 

这里是如何访问传递给您的选择器的自定义用户数据的原型:定义如上。因为我可能想传递多个数据段,所以我通过NSDictionary发送。

- (void)requestFinishedHandler:(NSNotification *)notification 
{ 
    resultDictionary = [notification userInfo]; 
} 
+0

非常感谢,只是澄清了一些事情,调度通知代码将在LocationHelper中的我的 - (void)locationManager:(CLLocationManager *)管理器didUpdateToLocation方法中,但是我应该在哪里放置代码[[NSNotificationCenter defaultCenter] addObserver :自。它是否在想要订阅通知的每个控制器的init方法中进行,并且我假定每个控制器都必须实现 - (void)requestFinishedHandler:(NSNotification *)通知方法是否正确? – Yogesh 2011-04-13 21:21:08

+0

对我来说,在控制器的viewDidAppear :(或viewDidLoad :)中调用addObserver更合理:因为您还想在viewDidDisappear中调用removeObserver:(或viewDidUnload :)。我不是100%确定如果你不注销观察员会发生什么,但我可以猜测这不完全是“最佳做法”。 – 2011-04-13 22:27:24

+0

非常感谢Cadaeic。 – Yogesh 2011-04-14 00:42:15

2
  1. 您所在的位置帮助应该是一个单身(这里有一个很好的例子:http://www.galloway.me.uk/tutorials/singleton-classes/

  2. 你应该使用的通知,而不是代表。位置助手单身人士应该在有新位置时发送通知,任何感兴趣的控制者都应该订阅这些通知。

+0

,我不要求单的一个例子,我要求的,如果它是一个单独的如何设置不同的视图控制器此singleton类的代表,单类有代表只有一个实例变量。 – Yogesh 2011-04-13 16:09:39

+0

您应该使用通知而不是委托。你的位置助手单身人士应该发送通知,并且对他们感兴趣的所有内容都应该订阅它们。 - 更新的答案。 – mbehan 2011-04-13 16:13:19

+0

我该怎么做? – Yogesh 2011-04-13 16:17:11

2

一块数据只应曾经代表(如“我的当前位置”,而你只能有一个)应该是什么地方,只能出现一次,像一个单身。

你已经有一个完美的单身人士,你已经使用。有些人会不同意我的看法(上帝知道他们有充足的理由),但对于这类数据,我没有第一个问题,就是把它全部留在我的App Delegate中。

当应用程序启动时,在App Delegate中,我将启动一个CLLocationManager,将App Delegate本身作为位置管理器的代理。我将保留返回的CLLocation作为委托的命名属性(比如“currentLocation”),并且在我从locationManager获取更新时经常覆盖它。

然后在我的各种视图控制器我可以说:

MyAppDelegate *del = (MyAppDelegate *)[UIApplication sharedApplication].delegate; 
CLLocation *current = del.currentLocation; 

这样,所有你的位置越来越/管理/存储发生在一个地方,你可以从任何地方在你的应用程序,它使一切漂亮干净

编辑:在回答“通过键值观察,你的意思是通知”的问题,答案是否定的。他们是完全不同的东西。

在任何您的视图控制器的 - 可能是在viewDidLoad中 - 你可以说:

MyAppDelegate *del = (MyAppDelegate *)[UIApplication sharedApplication].delegate; 
[del addObserver:self forKeyPath:@"currentLocation" options:0 context:nil]; 

,然后实现:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    MyAppDelegate *del = (MyAppDelegate *)object; 
    CLLocation *hereIAm = del.currentLocation; 
    // and then do whatever with that 
} 

你有一个关于改变一堆的细节,只是发生在该方法的参数中的那个键上,但是可能只是简单地返回到委托并取出你正在寻找的值。

可能要删除观察者viewDidUnload:

MyAppDelegate *del = (MyAppDelegate *)[UIApplication sharedApplication].delegate; 
[del removeObserver:self forKeyPath:@"currentLocation"]; 
+0

@丹,但问题与这种方法是当应用程序委托类中有更新的位置时,我的所有控制器如何得到通知。 – Yogesh 2011-04-13 16:08:07

+0

@Yogesh - 它不需要。它每次使用委托的'.currentLocation'属性来处理任何与位置有关的事情时,委托人的工作就是使事物保持最新状态。或者,如果您需要在位置更新的viewController中触发活动,则这种情况对于键值观察来说非常完美。 – 2011-04-13 17:23:46

+0

@Dan所以当你说键值观察时,你是指通知,因为mbehan和Cadaeic建议 – Yogesh 2011-04-13 21:22:23

相关问题