Note that there are some explanatory texts on larger screens.

plurals
  1. PONSURLConnection delegate methods on background thread
    primarykey
    data
    text
    <p><strong>EDIT2 - Rewrote the question</strong></p> <p>I want to do some web service communication in the background. I am using <a href="http://sudzc.com/" rel="nofollow">Sudzc</a> as the handler of HTTPRequests and it works like this:</p> <pre><code>SudzcWS *service = [[SudzcWS alloc] init]; [service sendOrders:self withXML:@"my xml here" action:@selector(handleOrderSending:)]; [service release]; </code></pre> <p>It sends some XML to the webservice, and the response (in this one, a Boolean) is handled in the selector specified:</p> <pre><code>- (void)handleOrderSending:(id)value { //some controls if ([value boolValue] == YES) { //my stuff } } </code></pre> <p>When I tried to use Grand Central Dispatch on my <code>sendOrders:withXML:action:</code> method, I noticed that the selector is not called. And I believe the reason for that is that <strong>NSURLConnection delegate messages are sent to the thread of which the connection is created</strong> But the thread does not live that long, it ends when the method finishes, killing any messages to the delegate.</p> <p>Regards</p> <p><strong>EDIT1</strong> <code>[request send]</code> method:</p> <pre><code>- (void) send { //dispatch_async(backgroundQueue, ^(void){ // If we don't have a handler, create a default one if(handler == nil) { handler = [[SoapHandler alloc] init]; } // Make sure the network is available if([SoapReachability connectedToNetwork] == NO) { NSError* error = [NSError errorWithDomain:@"SudzC" code:400 userInfo:[NSDictionary dictionaryWithObject:@"The network is not available" forKey:NSLocalizedDescriptionKey]]; [self handleError: error]; } // Make sure we can reach the host if([SoapReachability hostAvailable:url.host] == NO) { NSError* error = [NSError errorWithDomain:@"SudzC" code:410 userInfo:[NSDictionary dictionaryWithObject:@"The host is not available" forKey:NSLocalizedDescriptionKey]]; [self handleError: error]; } // Output the URL if logging is enabled if(logging) { NSLog(@"Loading: %@", url.absoluteString); } // Create the request NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL: url]; if(soapAction != nil) { [request addValue: soapAction forHTTPHeaderField: @"SOAPAction"]; } if(postData != nil) { [request setHTTPMethod: @"POST"]; [request addValue: @"text/xml; charset=utf-8" forHTTPHeaderField: @"Content-Type"]; [request setHTTPBody: [postData dataUsingEncoding: NSUTF8StringEncoding]]; if(self.logging) { NSLog(@"%@", postData); } } //dispatch_async(dispatch_get_main_queue(), ^(void){ // Create the connection conn = [[NSURLConnection alloc] initWithRequest: request delegate: self]; if(conn) { NSLog(@" POST DATA %@", receivedData); receivedData = [[NSMutableData data] retain]; NSLog(@" POST DATA %@", receivedData); } else { // We will want to call the onerror method selector here... if(self.handler != nil) { NSError* error = [NSError errorWithDomain:@"SoapRequest" code:404 userInfo: [NSDictionary dictionaryWithObjectsAndKeys: @"Could not create connection", NSLocalizedDescriptionKey,nil]]; [self handleError: error]; } } //}); //finished = NO; // while(!finished) { // // [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; // // } //}); } </code></pre> <p>The parts that are commented out are the various things I tried. The last part worked but I'M not sure if that's a good way. In the <code>NURLConnection</code> delegate method of the class, here is what happens:</p> <pre><code>- (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSError* error; if(self.logging == YES) { NSString* response = [[NSString alloc] initWithData: self.receivedData encoding: NSUTF8StringEncoding]; NSLog(@"%@", response); [response release]; } CXMLDocument* doc = [[CXMLDocument alloc] initWithData: self.receivedData options: 0 error: &amp;error]; if(doc == nil) { [self handleError:error]; return; } id output = nil; SoapFault* fault = [SoapFault faultWithXMLDocument: doc]; if([fault hasFault]) { if(self.action == nil) { [self handleFault: fault]; } else { if(self.handler != nil &amp;&amp; [self.handler respondsToSelector: self.action]) { [self.handler performSelector: self.action withObject: fault]; } else { NSLog(@"SOAP Fault: %@", fault); } } } else { CXMLNode* element = [[Soap getNode: [doc rootElement] withName: @"Body"] childAtIndex:0]; if(deserializeTo == nil) { output = [Soap deserialize:element]; } else { if([deserializeTo respondsToSelector: @selector(initWithNode:)]) { element = [element childAtIndex:0]; output = [deserializeTo initWithNode: element]; } else { NSString* value = [[[element childAtIndex:0] childAtIndex:0] stringValue]; output = [Soap convert: value toType: deserializeTo]; } } if(self.action == nil) { self.action = @selector(onload:); } if(self.handler != nil &amp;&amp; [self.handler respondsToSelector: self.action]) { [self.handler performSelector: self.action withObject: output]; } else if(self.defaultHandler != nil &amp;&amp; [self.defaultHandler respondsToSelector:@selector(onload:)]) { [self.defaultHandler onload:output]; } } [self.handler release]; [doc release]; [conn release]; conn = nil; [self.receivedData release]; } </code></pre> <p>The delegate is unable to send messages because the thread it is dies when <code>-(void)send</code> finishes.</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.
 

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