Получение обновлений CLLocation в фоновом потоке

Я пытаюсь реализовать (неконкурентную) NSOperation для обновления местоположения с помощью iPhone SDK. «Мясо» подкласса NSOperation выглядит примерно так:

- (void)start {
    // background thread set up by the NSOperationQueue
    assert(![NSThread isMainThread]);

    if ([self isCancelled]) {
        return;
    }

    self->locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.desiredAccuracy = self->desiredAccuracy;
    locationManager.distanceFilter = self->filter;
    [locationManager startUpdatingLocation];

    [self willChangeValueForKey:@"isExecuting"];
    self->acquiringLocation = YES;
    [self didChangeValueForKey:@"isExecuting"];
}

- (void)cancel {
    if ( ! self->cancelled ) {
        [self willChangeValueForKey:@"isCancelled"];
        self->cancelled = YES;
        [self didChangeValueForKey:@"isCancelled"];

        [self stopUpdatingLocation];
    }
}

- (BOOL)isExecuting {
    return self->acquiringLocation == YES;
}

- (BOOL)isConcurrent {
    return NO;
}

- (BOOL)isFinished {
    return self->acquiringLocation == NO;
}

- (BOOL)isCancelled {
    return self->cancelled;
}



- (void)stopUpdatingLocation {
    if (self->acquiringLocation) {
        [locationManager stopUpdatingLocation];

        [self willChangeValueForKey:@"isExecuting"];
        [self willChangeValueForKey:@"isFinished"];
        self->acquiringLocation = NO;  
        [self didChangeValueForKey:@"isExecuting"];
        [self didChangeValueForKey:@"isFinished"];
    }
    locationManager.delegate = nil;
}


- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    assert(![NSThread isMainThread]);

    // ... I omitted the rest of the code from this post

    [self stopUpdatingLocation];
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)theError {
    assert(![NSThread isMainThread]);
    // ... I omitted the rest of the code from this post
}

Теперь в основном потоке я создаю экземпляр этой операции и добавляю его в NSOperationQueue. Метод запуска вызывается, однако ни один из методов делегата -locationManager:... не вызывается. Я не понимаю, почему им никогда не звонят.

Я заставил интерфейс придерживаться протокола <CLLocationManagerDelegate>. Я позволяю NSOperationQueue управлять потоком для этой операции, поэтому все должно соответствовать документации CLLocationManagerDelegate:

Методы вашего объекта делегата вызываются из потока, в котором вы запустили соответствующие службы определения местоположения. Этот поток сам должен иметь активный цикл выполнения, подобный тому, который находится в основном потоке вашего приложения.

Я не уверен, что еще попробовать, чтобы это сработало. Может быть, это смотрит мне в лицо... Любая помощь приветствуется.

Заранее спасибо!


person octy    schedule 22.10.2010    source источник


Ответы (1)


Вам не хватает части «активный цикл выполнения». В конце метода запуска добавьте:

while (![self isCancelled])
  [[NSRunLoop currentRunLoop] runUntilDate:someDate];

person Alejandro    schedule 22.10.2010
comment
Так что это было прямо передо мной :) Я не думал, что мне нужно запускать цикл выполнения вручную из-за NSOperationQueue, управляющего потоком (и его циклом выполнения). Думаю, это не так. Спасибо! - person octy; 25.10.2010