Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There are two ways of fixing your problem:</p> <h3>The easy way out</h3> <p>is — as Dean suggests — using <code>+[NSURLConnection sendSynchronousRequest:returningResponse:error:]</code>, as you already are on a different thread. This has you covered — I'd say — 80-90% of the time, is really simple to implement and Just Works™.</p> <h3>The other way</h3> <p>is only slightly more complicated and has you covered for all the cases where the first method does not suffice — by visiting the root of your problem:</p> <p><code>NSURLConnection</code> works in conjunction with the runloop — and the threads managed by <code>NSOperationQueue</code> don't necessarily use (or even have!) an associated runloop.</p> <p>While calling <code>+[NSURLConnection connectionWithRequest:delegate:]</code> will implicitly create a runloop, if needed, <strong>it does not cause the runloop to actually run!</strong></p> <p><strong>This is your responsibility</strong>, when the <code>NSOperationQueue</code> you use is not the queue associated with the main thread.</p> <p>To do so, change your implementation of <code>fetchXMLWithCompletionHandler:</code> to look similar to the following:</p> <pre><code>- (void)fetchXMLWithCompletionHandler:(WAFetchXMLHandler)block { self.xmlHandler = block; // Declare a @property for the block with the copy attribute set self.mutableXMLData = [NSMutableData data]; // again, you should have a property for this... self.currentConnection = [NSURLConnection connectionWithRequest:request delegate:self]; // having a @property for the connection allows you to cancel it, if needed. self.connectionShouldBeRunning = YES; // ...and have a BOOL like this one, setting it to NO in connectionDidFinishLoad: and connection:didFailWithError: NSRunLoop *loop = [NSRunLoop currentRunLoop]; NSDate *neverExpire = [NSDate distantFuture]; BOOL runLoopDidIterateRegularly = YES; while( self.connectionShouldBeRunning &amp;&amp; runLoopDidIterateRegularly ) { runLoopDidIterateRegularly = [loop runMode:NSDefaultRunLoopMode beforeDate:neverExpire]; } } </code></pre> <p>With these small changes, you're good to go. Bonus: this is really flexible and (eventually) reusable throughout all your code — if you move the XML-parsing out of that class and make your handler simply take an <code>NSData</code>, an <code>NSError</code> and (optionally) an <code>NSURLResponse</code>.</p> <p>Since you probably don't want the clients of your loader to see and possibly mess with the properties I just suggested you should add, you can declare them in a class continuation.</p>
 

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