4

私のアプリケーションでは、 を介して非同期ネットワーク アクティビティをトリガーする信号がありますflattenMap。ネットワーク アクティビティの進行中にローディング インジケータを表示したいと考えています。

私の現在のソリューションはうまくいきます:

  [[[[self.signInButton
    rac_signalForControlEvents:UIControlEventTouchUpInside]
    doNext:^(id x) {
      // show the loading indicator as a side-effect
      self.loadingIndicator.hidden = NO;
    }]
    flattenMap:^id(id x) {
      return [self doSomethingAsync];
    }]
    subscribeNext:^(NSNumber *result) {
      // hide the indicator again
      self.loadingIndicator.hidden = YES;
      // do something with the results
    }];

これは機能しますが、上記のコードを変更してhidden、ロード インジケーターのプロパティをシグナル経由で設定できるようにしたいと考えています。

これは可能ですか?

私のアプリの他の場所には、要素の可視性がいくつかの異なる「イベント」に依存する、より複雑な要件があります。シグナルを介してこれらを構成できる方がはるかに優れています。

4

3 に答える 3

2

あなたの信号は次のように見えます: whensignInButtonSignalまたはresultSignalsend a value, invert the last value of hidden. それは簡単です。

[[[hiddenSig replayLast] not] sample:[RACSignal merge:@[signInButtonSignal, resultSignal]];

私はあなたに似た状況でまさにその構成を使用しています。演算子にラップするといいかもしれません:

- (RACSignal *)toggle:(RACSignal *)toggler
{
    return [[[self replayLast] not] sample:toggler];
}

次に、あなたはちょうど持っています

[hiddenSig toggle:[RACSignal merge:@[signInButtonSignal, resultSignal]]];

もう 1 つの可能性は、状態をマッピング ブロックに関連付けるクラス メソッドである可能性があります。

+ (RACSignal *)toggle:(RACSignal *)toggler initially:(BOOL)initial
{
    __block BOOL currVal = initial;
    return [[toggler map:^id (id _) {
        currVal = !currVal;
        return @(currVal);
    }] startWith:@(initial)];
}

その後

[RACSignal toggle:[RACSignal merge:@[signInButtonSignal, resultSignal]]
        initially:NO];
于 2014-01-10T08:24:45.643 に答える
2

Josh からの回答はかなり役に立ちましたが、最終的にはより簡単な解決策を見つけました。パイプラインを 2 つのシグナルに分割するだけです。1 つはボタンの押下用で、もう 1 つは後続の非同期アクティビティ用です。次に、2つをマージして、loadingIndicatorhiddenプロパティにバインドするために使用したシグナルを提供しました。

// a signal that triggers sign-in
RACSignal *signInStartSignal = [self.signInButton
                         rac_signalForControlEvents:UIControlEventTouchUpInside];

// a signal that emits the sign in result
RACSignal *signInResultSignal =
  [signInStartSignal
    flattenMap:^id(id x) {
      return [self doSomethingAsync];
    }];

[signInResultSignal
  subscribeNext:^(NSNumber *result) {
    // do something based on the result
  }];

// merge the two signals 
RACSignal *signInInProgress =
  [[RACSignal merge:@[signInResultSignal, signInStartSignal]]
    map:^id(id value) {
      // if the signal value is a UIButton, the signal that
      // just fired was the signInStartSignal
      return @(![[value class] isSubclassOfClass:[UIButton class]]);
    }];

RAC(self.signInFailureText,hidden) = signInInProgress;
于 2014-01-12T18:47:33.710 に答える