Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Dealing with asynchronous methods is a pain ;)</p> <p>In your case its guaranteed that the completion block will execute on the specified queue. However, you need to ensure that the queue has a max concurrent operations count of 1, otherwise concurrent access to shared resources is not safe. That's a classic race <a href="http://en.wikipedia.org/wiki/Race_condition" rel="nofollow">http://en.wikipedia.org/wiki/Race_condition</a>. The max concurrent operations of a NSOperationQueue can be set with a property.</p> <p>In general, completion handlers may execute on any thread, unless otherwise specified.</p> <p>Dealing with asynchronous methods gets a lot easier when using a concept called "Promises" <a href="http://en.wikipedia.org/wiki/Promise_(programming)" rel="nofollow">http://en.wikipedia.org/wiki/Promise_(programming)</a>. Basically, "Promises" represent a result that will be evaluated in the future - nonetheless the promise itself is immediately available. Similar concepts are named "futures" or "deferred".</p> <p>There is an implementation of a promise in Objective-C on GitHub: RXPromise. When using it you also get safe access from within the handler blocks to shared resources. An implementation would look as follows:</p> <pre><code>-(RXPromise*) fetchImageFromURL:(NSString*)urlString queue:(NSOperationQueue*) queue { @autoreleasepool { RXPromise* promise = [[RXPromise alloc] init]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]]; [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { if (data != nil) { [promise fulfillWithValue:data]; } else { // There was an error [promise rejectWithReason:error]; }; }]; return promise; } } </code></pre> <p>Then call it:</p> <pre><code>- (void) fetchImages { ... for (NSUInteger index = 0; index &lt; N; ++index) { NSString* urlString = ... [self fetchImageFromURL:urlString, self.queue] .then(^id(id data){ [self.allImages replaceObjectAtIndex:index withObject:[UIImage imageWithData:data]]; return @"OK"; }, ^id(NSError* error) { [self.allImages replaceObjectAtIndex:index withObject:[UIImage imageNamed:@"error.png"]]; return error; }); } } </code></pre>
    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.
 

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