良い質問!通常、このようなユースケースにはRACMulticastConnectionを使用しますが、信号を後で再アクティブ化できるようにするため、接続だけでは適していません。
おそらく最も簡単な答えは、接続がどのように機能するかを模倣することですが、必要な特定の動作を備えています。基本的に、特定の時点でのサブスクライバーの数を追跡し、その数に基づいて場所の更新を開始/停止します。
locationSubject
プロパティを追加することから始めましょう。新しいサブスクライバーには常に最新の送信場所をすぐに取得してもらいたいため、サブジェクトはRACReplaySubjectである必要があります。その件名で更新を実装するのは簡単です。
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
[self.locationSubject sendNext:locations.lastObject];
}
次に、購読者数を追跡して増減するシグナルを実装します。これは、numberOfLocationSubscribers
整数プロパティを使用して機能します。
- (RACSignal *)currentLocationSignal {
return [RACSignal createSignal:^(id<RACSubscriber> subscriber) {
@synchronized (self) {
if (self.numberOfLocationSubscribers == 0) {
[self.locationManager startUpdatingLocation];
}
++self.numberOfLocationSubscribers;
}
[self.locationSubject subscribe:subscriber];
return [RACDisposable disposableWithBlock:^{
@synchronized (self) {
--self.numberOfLocationSubscribers;
if (self.numberOfLocationSubscribers == 0) {
[self.locationManager stopUpdatingLocation];
}
}
}];
}];
}
上記のコードでは+createSignal:
、返されたシグナルに新しいサブスクライバーが追加されるたびに、ブロックが呼び出されます。その場合:
- サブスクライバーの数が現在ゼロであるかどうかを確認します。その場合、追加したばかりのサブスクライバーが最初のサブスクライバーであるため、位置情報の更新を有効にする (または再度有効にする) 必要があります。
- サブスクライバーを に直接フックする
locationSubject
ため、後者からの値は自動的に前者に供給されます。
- その後、サブスクリプションが破棄された時点でカウントを減らし、必要に応じて位置情報の更新を停止します。
あとは、起動時にサブスクライブしcurrentLocationSignal
、数秒後に自動的にサブスクライブを解除するだけです。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Use a capacity of 1 because we only ever care about the latest
// location.
self.locationSubject = [RACReplaySubject replaySubjectWithCapacity:1];
[[self.currentLocationSignal
takeUntil:[RACSignal interval:3]]
subscribeCompleted:^{
// We don't actually need to do anything here, but we need
// a subscription to keep the location updating going for the
// time specified.
}];
return YES;
}
これはすぐにサブスクライブし、シグナルが最初の値を送信しself.currentLocationSignal
たときにそのサブスクリプションを自動的に破棄します。+interval:
興味深いことに、-[RACMulticastConnection autoconnect]
以前-currentLocationSignal
は上記のように動作していましたが、副作用が非常に予測不可能になるため、動作が変更されました。このユース ケースは安全なはずですが、自動再接続が恐ろしい場合もあります (ネットワーク リクエストを行うときやシェル コマンドを実行するときなど)。