2011-04-13 61 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

相關問題