Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>So, there are two major things going on here:</p> <ol> <li>You want to share some side effects (in this case, fetching a token) without re-triggering them every time there's a new subscriber.</li> <li>You want anyone subscribing to <code>-getToken</code> to get the same values no matter what.</li> </ol> <p>In order to share side effects (#1 above), we'll use <a href="https://github.com/github/ReactiveCocoa/blob/83e23a96e726c99a444e83f306271d0e7d981379/ReactiveCocoaFramework/ReactiveCocoa/RACMulticastConnection.h" rel="noreferrer">RACMulticastConnection</a>. Like the documentation says:</p> <blockquote> <p>A multicast connection encapsulates the idea of sharing one subscription to a signal to many subscribers. This is most often needed if the subscription to the underlying signal involves side-effects or shouldn't be called more than once.</p> </blockquote> <p>Let's add one of those as a private property on the API client class:</p> <pre><code>@interface APIClient () @property (nonatomic, strong, readonly) RACMulticastConnection *tokenConnection; @end </code></pre> <p>Now, this will solve the case of N current subscribers that all need the same future result (API calls waiting on the request token being in-flight), but we still need something else to ensure that <em>future</em> subscribers get the same result (the already-fetched token), no matter when they subscribe.</p> <p>This is what <a href="https://github.com/github/ReactiveCocoa/blob/83e23a96e726c99a444e83f306271d0e7d981379/ReactiveCocoaFramework/ReactiveCocoa/RACReplaySubject.h" rel="noreferrer">RACReplaySubject</a> is for:</p> <blockquote> <p>A replay subject saves the values it is sent (up to its defined capacity) and resends those to new subscribers. It will also replay an error or completion.</p> </blockquote> <p>To tie these two concepts together, we can use <a href="https://github.com/github/ReactiveCocoa/blob/83e23a96e726c99a444e83f306271d0e7d981379/ReactiveCocoaFramework/ReactiveCocoa/RACSignal%2BOperations.h#L238-L241" rel="noreferrer">RACSignal's -multicast: method</a>, which turns a normal signal into a connection <em>by using</em> a specific kind of subject.</p> <p>We can hook up most of the behaviors at initialization time:</p> <pre><code>- (id)init { self = [super init]; if (self == nil) return nil; // Defer the invocation of -reallyGetToken until it's actually needed. // The -defer: is only necessary if -reallyGetToken might kick off // a request immediately. RACSignal *deferredToken = [RACSignal defer:^{ return [self reallyGetToken]; }]; // Create a connection which only kicks off -reallyGetToken when // -connect is invoked, shares the result with all subscribers, and // pushes all results to a replay subject (so new subscribers get the // retrieved value too). _tokenConnection = [deferredToken multicast:[RACReplaySubject subject]]; return self; } </code></pre> <p>Then, we implement <code>-getToken</code> to trigger the fetch lazily:</p> <pre><code>- (RACSignal *)getToken { // Performs the actual fetch if it hasn't started yet. [self.tokenConnection connect]; return self.tokenConnection.signal; } </code></pre> <p>Afterwards, anything that subscribes to the result of <code>-getToken</code> (like <code>-requestSignalWithURLRequest:</code>) will get the token if it hasn't been fetched yet, start fetching it if necessary, or wait for an in-flight request if there is one.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload