Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Iterative algorithm</strong>:</p> <ul> <li>Create a <code>__block</code> variable (<code>int urlNum</code>) to keep track of the current URL (inside an <code>NSArray</code> of them).</li> <li>Have the onUrlComplete block fire off the next request until all URLs have been loaded.</li> <li>Fire the first request.</li> <li>When all URLs have been loaded, do the "//success!" dance.</li> </ul> <p>Code written without the aid of XCode (meaning, there may be compiler errors -- will fix if necessary):</p> <pre><code>- (void)loadUrlsAsynchronouslyIterative:(NSArray *)urls { __block int urlNum = 0; void(^onUrlComplete)(int) = nil; //I don't remember if you can call a block from inside itself. onUrlComplete = ^(int status) { if (urlNum &lt; urls.count) { id nextUrl = urls[urlNum++]; [remoteAPIWithURL:nextUrl success:onUrlComplete]; } else { //success! } } onUrlComplete(0); //fire first request } </code></pre> <p><strong>Recursive algorithm</strong>:</p> <ul> <li>Create a method to load all the remaining URLs.</li> <li>When remaining URLs is empty, fire "onSuccess".</li> <li>Otherwise, fire request for the next URL and provide a completion block that recursively calls the method with all but the first remaining URLs.</li> <li>Complications: we declared the "onSuccess" block to accept an <code>int status</code> parameter, so we pass the last status variable down (including a "default" value).</li> </ul> <p>Code written without the aid of XCode (<em>bug disclaimer here</em>):</p> <pre><code>- (void)loadUrlsAsynchronouslyRecursive:(NSArray *)remainingUrls onSuccess:(void(^)(int status))onSuccess lastStatus:(int)lastStatus { if (remainingUrls.count == 0) { onSuccess(lastStatus); return; } id nextUrl = remainingUrls[0]; remainingUrls = [remainingUrls subarrayWithRange:NSMakeRange(1, remainingUrls.count-1)]; [remoteAPIWithUrl:nextUrl onSuccess:^(int status) { [self loadUrlsAsynchronouslyRecursive:remainingUrls onSuccess:onSuccess lastStatus:status]; }]; } //fire first request: [self loadUrlsAsynchronouslyRecursive:urls onSuccess:^(int status) { //success here! } lastStatus:0]; </code></pre> <p><strong>Which is better</strong>?</p> <ul> <li>The iterative algorithm is simple and concise -- if you're comfortable playing games with <code>__block</code> variables and scopes.</li> <li>Alternatively, the recursive algorithm doesn't require <code>__block</code> variables and is fairly simple, as recursive algorithms go.</li> <li>The recursive implementation is more re-usable that the iterative one (as implemented).</li> <li>The recursive algorithm might leak (it requires a reference to <code>self</code>), but there are several ways to fix that: make it a function, use <code>__weak id weakSelf = self;</code>, etc.</li> </ul> <p><strong>How easy would it be to add error-handling</strong>?</p> <ul> <li>The iterative implementation can easily be extended to check the value of <code>status</code>, at the cost of the <code>onUrlComplete</code> block becoming more complex.</li> <li>The recursive implementation is perhaps not as straight-forward to extend -- primarily because it is re-usable. Do you want to cancel loading more URLs when the status is such-and-such? Then pass down a status-checking/error-handling block that accepts <code>int status</code> and returns <code>BOOL</code> (for example <code>YES</code> to continue, <code>NO</code> to cancel). Or perhaps modify <code>onSuccess</code> to accept both <code>int status</code> and <code>NSArray *remainingUrls</code> -- but you'll need to call <code>loadUrlsAsynchronouslyRecursive...</code> in your <code>onSuccess</code> block implementation.</li> </ul>
    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. 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.
 

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