2012-02-12 1 views
2

Я пытаюсь отправить обновление местоположения с новым местоположением в качестве объекта уведомления. Когда я это делаю, я получаю ошибку «EXC_BAD_ACCESS», когда пытаюсь получить доступ к данным из уведомления. Если я выполню «po location», я вижу данные, но мне непонятно, почему я не могу их приобрести. При настройке наблюдателя я также пытался назначить параметр объекта переменной-члену, но тогда locationUpdate никогда не вызывается.Как получить данные из объекта NSNotification?

Вот мой код (обратите внимание, что ARC включена):

// LocationController.h

@protocol LocationDelegateProtocol 
@required 
    - (void)locationUpdate:(CLLocation *)location; 
@end 

@interface LocationController : NSObject <CLLocationManagerDelegate> { 
    CLLocationManager *locationManager; 
    id delegate; 
} 

@property(nonatomic, retain) CLLocationManager *locationManager; 
@property(nonatomic, strong) id delegate; 

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation; 

+ (LocationController *)sharedInstance; // this class is a singleton 

@end 

// LocationController.m

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { 
    [Notification locationChanged:newLocation]; 
} 

// Notification.h

@interface Notification : NSObject 
    + (void)locationChanged:(CLLocation *)newLocation; 
@end 

extern NSString *const kLocationChanged; 

// Notification.m

NSString *const kLocationChanged = @"NewLocation"; 

[[NSNotificationCenter defaultCenter] postNotificationName:kLocationChanged object:newLocation]; 

// ViewController.h

@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, LocationDelegateProtocol> { 
    ... 
} 
... 
- (void)locationUpdate:(CLLocation *)location; 

@end 

// ViewController.m

- (void)setupNotifications { 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(locationUpdate:) name:kLocationChanged object:nil]; 
    // I've tried setting object to a member var "CLLocation *objectFromNotification", but then locationUpdate() is never called. 
} 

- (void)locationUpdate:(NSNotification *)notification {  
    CLLocation *location = (CLLocation *) [notification object]; 
    // program receives signal "EXC_BAD_ACCESS" when executing NSLog below. I can see data inside location when I execute "po location". 
    NSLog(@"latitude = %@, longitude = %@",location.coordinate.latitude, location.coordinate.longitude); 

ответ

4

Изменить спецификатор формата в вашем NSLog от% @ на% е , Вы пытаетесь получить доступ к значению float как объекта!

+0

LOL. У меня было% f для начала, но у меня были другие недостатки и я играл с классами. После исправления некоторых других недостатков я забыл изменить его. Я предположил, что я не исправил исходную проблему, что и сделал. Спасибо за обнаружение :) – TERACytE

+0

Нет проблем. Иногда бывает, что мы пропускаем мелочи. – cocoakomali

2

NSNotifications есть словарь с ними по имени userInfo, где вы можете разместить информацию, которую хотите отправить с уведомлением.

Я собираюсь исправить ваш код, как будто он идет назад ... так голый со мной. Вы действительно не использовали класс NSNotification, поскольку он обычно (или должен использоваться) использоваться.

Чтобы исправить эту ситуацию, мы должны сделать кучу вещей. Значение object сообщения NSNotification - это объект, который отправляет NSNotification, а не объект, который вы хотите передать с ним.

Добавить объект CLLocation в словарь и передать его в качестве словаря userInfo. Кроме того, нет никаких оснований для этого пользовательского материала класса уведомлений, который у вас есть. Таким образом, вы можете избавиться от Notification.h и Notification.m

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { 
    NSString *const kLocationChanged = @"NewLocation"; 
    NSDictionary *locationDict = [NSDictionary dictionaryWithObject:newLocation forKey:@"Location"]; 
    [[NSNotificationCenter defaultCenter] postNotificationName:kLocationChanged object:nil userInfo:locationDict]; 
} 

Так что теперь мы публикуем информацию о местоположении с уведомлением. Затем обработайте его, когда получите уведомление.

- (void)locationUpdate:(NSNotification *)notification {  
    CLLocation *location = [[notification userInfo] valueForKey:@"Location"]; 

    NSLog(@"latitude = %f, longitude = %f",location.coordinate.latitude, location.coordinate.longitude); 
} 

Кроме того, изменить заголовок вид контроллера на следующее:

@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, LocationDelegateProtocol> { 
    ... 
} 
... 
- (void)locationUpdate:(NSNotification *)notif; 

@end 
+0

Моя интерпретация документации на https://developer.apple.com/library/mac/# documentation/Cocoa/Reference/Foundation/Classes/nsnotification_Class/Reference/Reference.html - это допустимо: «Объектом является любой объект, который плакат уведомления хочет отправить наблюдателям этого уведомления « – TERACytE

+0

В самом деле, вы можете делать все, что хотите, это преимущество программиста. Проблема с вашей текущей реализацией возникает, когда вам нужна дополнительная информация, несколько фрагментов информации или вам нужно знать, какой объект отправил уведомление. Следующая строка из той же документации: «Объект - это любой объект, который плакат уведомления хочет отправить наблюдателям этого уведомления (обычно это объект, который отправил уведомление). В словаре хранятся другие связанные объекты, если они есть «. – ColdLogic