10

私はデモンストレーション アプリを作成しており、ReactiveCocoaの デザイン パターンにできるだけ準拠しようとしています。アプリの機能は次のとおりです。

  • デバイスの場所を見つける
  • ロケーションキーが変更されるたびに、以下をフェッチします。
    • 現在の天気
    • 毎時予報
    • 毎日の予報

したがって、順序は、1) 場所を更新する、2) 3 つの天候フェッチをすべてマージする、のようになります。WeatherManager気象オブジェクト、位置情報、および手動で更新するメソッドを公開するシングルトンを構築しました。このシングルトンはCLLocationManagerDelegateプロトコルに準拠しています。ロケーション コードは非常に基本的なものなので、省略します。唯一の興味深い点は次のとおりです。

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    // omitting accuracy & cache checking
    CLLocation *location = [locations lastObject];
    self.currentLocation = location;
    [self.locationManager stopUpdatingLocation];
}

気象条件の取得はすべて非常に似ているためRACSignal、URL から JSON を取得するための を生成するメソッドを構築しました。

- (RACSignal *)fetchJSONFromURL:(NSURL *)url {
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSURLSessionDataTask *dataTask = [self.session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            if (! error) {
                NSError *jsonError = nil;
                id json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
                if (! jsonError) {
                    [subscriber sendNext:json];
                }
                else {
                    [subscriber sendError:jsonError];
                }
            }
            else {
                [subscriber sendError:error];
            }

            [subscriber sendCompleted];
        }];

        [dataTask resume];

        return [RACDisposable disposableWithBlock:^{
            [dataTask cancel];
        }];
    }];
}

これにより、メソッドをきれいに保つことができるので、URL を構築して RACSignal を返す 3 つの短いメソッドができました。ここで良いことは、JSON を解析して適切なプロパティを割り当てるための副作用を作成できることです (注:ここではMantleを使用しています)。

- (RACSignal *)fetchCurrentConditions {
    // build URL
    return [[self fetchJSONFromURL:url] doNext:^(NSDictionary *json) {
        // simply converts JSON to a Mantle object
        self.currentCondition = [MTLJSONAdapter modelOfClass:[CurrentCondition class] fromJSONDictionary:json error:nil];
    }];
}

- (RACSignal *)fetchHourlyForecast {
    // build URL
    return [[self fetchJSONFromURL:url] doNext:^(NSDictionary *json) {
        // more work
    }];
}

- (RACSignal *)fetchDailyForecast {
    // build URL
    return [[self fetchJSONFromURL:url] doNext:^(NSDictionary *json) {
        // more work
    }];
}

最後に、-init私のシングルトンで、RAC オブザーバーをその場所に設定しました。場所が変わるたびに天気を取得して更新したいからです。

[[RACObserve(self, currentLocation)
 filter:^BOOL(CLLocation *newLocation) {
     return newLocation != nil;
 }] subscribeNext:^(CLLocation *newLocation) {
     [[RACSignal merge:@[[self fetchCurrentConditions], [self fetchDailyForecast], [self fetchHourlyForecast]]] subscribeError:^(NSError *error) {
         NSLog(@"%@",error.localizedDescription);
     }];
 }];

すべてが正常に機能しますが、フェッチとプロパティの割り当てを構造化するためのリアクティブな方法から逸脱しているのではないかと心配しています。でシーケンスを実行しようとしまし-then:たが、希望どおりのセットアップを行うことができませんでした。

また、非同期フェッチの結果をシングルトンのプロパティにバインドするクリーンな方法を見つけようとしていましたが、それを機能させるのに苦労しました。フェッチ s を「拡張」する方法を理解できませんでしたRACSignal(注:-doNext:それぞれのアイデアはそこから生まれました)。

これを解決するための助けやリソースは本当に素晴らしいでしょう. ありがとう!

4

2 に答える 2