1

I am wanting to create a synchronous nsurlconnection request. Yes I know its stupid and I know the limitations (freezing the UI) however the reason I would like to implement this to garnet the data I am receiving from the server is received in the order it is sent, which Is one of the benefits of a synchronous connection.. if I read correctly.

I am going to be using Grand Central Dispatch to achieve some multi threading in order to run the sync request and not have it effect the UI of the main thread... but this can come later for now I would like to master the sync connection.

The one issue is that I'm not exactly sure how to set my connection as synchronous..

Here is my code.

- (void)loadComics{

    [comics removeAllObjects]; //clears object of any old values
    [[self tableView] reloadData];

    NSURL *url = [NSURL URLWithString:@"http://www.comicbookresources.com/feed.php?feed=previews"];

    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];

    //clear any existing connection
    if (connectionInProgress) {
        [connectionInProgress cancel];
        [connectionInProgress release];
    }

    [xmlData release];
    xmlData = [[NSMutableData alloc] init];

    connectionInProgress = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    [xmlData appendData:data];
}

- (void) connectionDidFinishLoading:(NSURLConnection *)connection{

    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];

    [parser setDelegate:self];

    [parser parse];

    [parser release];
    [[self tableView] reloadData];
}

any examples would be great.

C.Johns
  • 10,185
  • 20
  • 102
  • 156
  • What do you mean by "garnet the data I am receiving from the server is received in the order it is sent"? Synchronous networking—even in a background thread—is almost always an indicator of a bad design. – Nick Hutchinson Feb 12 '12 at 21:36
  • well as far as I am aware async can sometimes receive data in an incorrect order. The database engine I am having to communicate with requires me to do this syncronosly as its important to receive the data in the correct order. Why do you think its an indicator of bad design, I'm interested in your perspective as I am currently only doing as I have been instructed however if I can put together a case to the database engineer as to why he should so otherwise I would be intrested in hearing your opinion. – C.Johns Feb 12 '12 at 21:51
  • 1
    That's not correct — you don't have to worry about receiving `connection:didReceiveData:` callbacks out of order. What you've written looks fine — you can just concatenate the chunks of data as you receive them, and do something with the complete data in `connectionDidFinishLoading:`. This would only be a problem if, for some reason, you were running multiple NSURLConnections at the same time, all with the same delegate. But you generally don't want to do that! – Nick Hutchinson Feb 12 '12 at 22:34
  • okay cool I get what your saying thanks for the clarification. – C.Johns Feb 12 '12 at 22:46

2 Answers2

9

If you want a synchronous connection, you must use +sendSynchronousRequest:returningResponse:error there is no other easy way to do this.

Note that it's deprecated in favor of NSURLSession, but it doesn't support synchronous connection directly.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
4

Synchronous networking, even in a background thread, isn't the way to go. You can't properly support cancellation, and you're wasting resources, spinning off a background thread that will spend most of its time idle. While this is mostly an academic concern if you're only sending off one URL request, it can be another story if you send out a large number of them.

You don't have to worry about receiving connection:didReceiveData: callbacks out of order. What you've written looks fine — you can just concatenate the chunks of data as you receive them, and do something with the complete data in connectionDidFinishLoading:.

What you do have to worry about is receiving multiple connection:didReceiveResponse: callbacks in the case of redirects. See Apple's documentation. In this case, you'll simply want to reset the data you've accumulated so far with [xmlData setLength:0].

Finally, if you can require iOS5 or 10.7 and don't need the complexity of a NSURLConnection delegate, then the new +[sendAsynchronousRequest:queue:completionHandler:] method is a nice, non-evil alternative to +[sendSynchronousRequest:returningResponse:error].

Nick Hutchinson
  • 5,044
  • 5
  • 33
  • 34