Как я получаю данные от объекта NSNotification? - PullRequest
2 голосов
/ 12 февраля 2012

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

Вот мой код (обратите внимание, что 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); 

Ответы [ 2 ]

4 голосов
/ 12 февраля 2012

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

2 голосов
/ 12 февраля 2012

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
...