Задний план
Я действительно взволнован фреймворком ReactiveCocoa и его потенциалом, поэтому я решил, что собираюсь стиснуть зубы и написать свое первое приложение, используя его. В моем приложении я уже написал различные сервисы и делегаты, но теперь мне нужно их «Reactive-Cocoa-ise», чтобы я мог работать с фактической стороной GUI.
Тем не менее, чтобы лучше понять это, я пишу простой код, чтобы опробовать концепции. В этом случае написание оболочки для CLLocationManagerDelegate.
В реальном приложении вариант использования будет таким:
- 1) Когда приложение загружается (viewDidLoad), затем 2) Попытка получить местоположение устройства с помощью
- 2.1) если службы определения местоположения не включены, то
- 2.1.1) проверить статус авторизации, и если разрешено
startMonitoringSignificantLocationChanges
, - 2.1.2) иначе вернуть ошибку
- 2.2) иначе (услуги определения местоположения включены)
- 2.2.1) если последнее местоположение менеджера местоположения было «недавним» (6 часов или меньше), вернуть это
- 2.2.2) иначе startMonitoringSignificantLocationChanges
- 3) при возврате локации (или сразу, или через
locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
) то тожеstopMonitoringSignificantLocationChanges
- 4) Если код, который вызывает LocationManagerDelegate, получает и получает ошибку, то запросите у делегата фиксированное значение «по умолчанию».
- 5) Затем следующий фрагмент кода использует местоположение (выбранное или заданное по умолчанию) для запуска и выполнения множества вызовов сторонних сервисов (вызовы веб-сервисов и т. д.).
Вы можете увидеть тестовый набор по адресу https://github.com/ippoippo/reactive-core-location-test
Обеспокоенность
Привязь «работает» в том смысле, что она снимается и определяет местоположение. Тем не менее, я действительно обеспокоен тем, что делаю это правильно.
Рассмотрим этот код
RACSignal *fetchLocationSignal = [lmDelegate latestLocationSignal];
RACSignal *locationSignal = [fetchLocationSignal catch:^RACSignal *(NSError *error) {
NSLog(@"Unable to fetch location, going to grab default instead: %@", error);
CLLocation *defaultLocation = [lmDelegate defaultLocation];
NSLog(@"defaultLocation = [%@]", defaultLocation);
// TODO OK, so now what. I just want to handle the error and
// pass back this default location as if nothing went wrong???
return [RACSignal empty];
}];
NSLog(@"Created signal, about to bind on self.locationLabel text");
RAC(self.locationLabel, text) = [[locationSignal filter:^BOOL(CLLocation *newLocation) {
NSLog(@"Doing filter first, newLocation = [%@]", newLocation);
return newLocation != nil;
}] map:^(CLLocation *newLocation) {
NSLog(@"Going to return the coordinates in map function");
return [NSString stringWithFormat:@"%d, %d", newLocation.coordinate.longitude, newLocation.coordinate.latitude];
}];
Вопросы
- 1) Как обрабатывать ошибки? Я могу использовать
catch
, что затем дает мне возможность запросить у делегата местоположение по умолчанию. Но затем я застрял на том, как передать это местоположение по умолчанию в качестве сигнала? Или мне просто изменить методdefaultLocation
, чтобы он возвращалRACSignal
, а неCLLocation
?? - 2) Когда я возвращаю местоположение, это должно быть сделано как
sendNext
илиsendCompleted
? В настоящее время он закодирован какsendNext
, но похоже, что его можно было бы сделать какsendCompleted
. - 3) На самом деле, зависит ли ответ на этот вопрос от того, как я создаю делегата. Это тестовое приложение создает нового делегата каждый раз при загрузке представления. Это что-то, что я должен сделать, я должен сделать делегата синглтоном. Если это синглтон, то sendNext кажется правильным. Но если бы это означало, что я вместо этого перемещаю код, который у меня есть в
latestLocationSignal
в моем делегате, в метод инициализации?
Извиняюсь за бессвязный вопрос (вопросы), просто кажется, что у меня в голове крутится круг.