Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Wrap your asynchronous NSURLConnection request in a helper method which has a completion block as a parameter:</p> <p><code>-(void) asyncDoSomething:(void(^)(id result)completionHandler ;</code></p> <p>This method should be implemented in the <code>NSURLConnectionDelegate</code>. For details see the example implementation and comments below.</p> <p>Elsewhere, in your action method:</p> <p>Set the completion handler. The block will dispatch further on the main thread, and then perform anything appropriate to update the table data, unless the result was an error, in which case you should display an alert.</p> <pre><code>- (IBAction) recordButtonPressed { [someController asyncConnectionRequst:^(id result){ if (![result isKindOfClass:[NSError class]]) { dispatch_async(dispatch_get_main_queue(), ^{ // We are on the main thread! someController.tableData = result; }); } }]; } </code></pre> <p>The Implementation of the method <code>asyncConnectionRequst:</code> <em>could</em> work as follows: take the block and hold it in an ivar. When it is appropriate call it with the correct parameter. However, having blocks as ivars or properties will increase the risk to inadvertently introduce circular references. </p> <p>But, there is a better way: a wrapper block will be immediately dispatched to a <em>suspended</em> serial dispatch queue - which is hold as an ivar. Since the queue is suspended, they will not execute any blocks. Only until after the queue will be resumed, the block executes. You resume the queue in your <code>connectionDidFinish:</code> and <code>connectionDidFailWithError:</code> (see below):</p> <p>In your NSURLConnectionDelegate:</p> <pre><code>-(void) asyncConnectionRequst:(void(^)(id result)completionHandler { // Setup and start the connection: self.connection = ... if (!self.connection) { NSError* error = [[NSError alloc] initWithDomain:@"Me" code:-1234 userInfo:@{NSLocalizedDescriptionKey: @"Could not create NSURLConnection"}]; completionHandler(error); }); return; } dispatch_suspend(self.handlerQueue); // a serial dispatch queue, now suspended dispatch_async(self.handlerQueue, ^{ completionHandler(self.result); }); [self.connection start]; } </code></pre> <p>Then in the NSURLConnectionDelegate, dispatch a the handler and resume the handler queue:</p> <pre><code>- (void) connectionDidFinishLoading:(NSURLConnection*)connection { self.result = self.responseData; dispatch_resume(self.handlerQueue); dispatch_release(_handlerQueue), _handlerQueue = NULL; } </code></pre> <p>Likewise when an error occurred:</p> <pre><code>- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { self.result = error; dispatch_resume(self.handlerQueue); dispatch_release(_handlerQueue), _handlerQueue = NULL; } </code></pre> <p>There are even better ways, which however involve a few more basic helper classes which deal with asynchronous architectures which at the end of the day make your async code look like it were synchronous:</p> <pre><code>-(void) doFourTasksInAChainWith:(id)input { // This runs completely asynchronous! self.promise = [self asyncWith:input] .then(^(id result1){return [self auth:result1]);}, nil) .then(^(id result2){return [self fetch:result2];}, nil) .then(^(id result3){return [self parse:result3];}, nil) .then(^(id result){ self.tableView.data = result; return nil;}, ^id(NSError* error){ ... }) // later eventually, self.promise.get should contain the final result } </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. This table or related slice is empty.
    1. This table or related slice is empty.
    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