views:

172

answers:

3

I've been reading several threads and questions about this issue but I didn't find the solution.

I have some asynchronous calls performed with

[NSURLConnection connectionWithRequest:anURLRequest delegate:self];

The problem is that I want the interface to be operative but it is blocked until the connection is finished.

Is this solved launching another thread? Where is exactly the problem?

EDIT

Ok, after retrieve data I parse it with NSXMLParser, that do it synchronously and blocks main thread. Is this correct? Then, maybe I need to parse in another thread. Anyone has a guide?

EDIT 2

Ok, I parse the results on a background thread and it doesn't blocks UI.

+1  A: 

From the docs:

Messages to the delegate will be sent on the thread that calls this method. For the connection to work correctly the calling thread’s run loop must be operating in the default run loop mode.

Are you sure that this code is being called on a run loop in default mode and not from a thread created by yourself with a different type of run loop mode?

Jasarien
I don't create any thread on any part of my app. But I don't know if the system creates another thread by itself and I miss the thing. Is this possible?
Espuz
+1  A: 

The UI should not be locking up when you use connectionWithRequest. Try creating a label in your UI and have your connection update it with the current amount of data, like so:

- (void)downloadContentFromUrl:(NSURL *)url {   
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0];
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    if (connection) {
        receivedData = [[NSMutableData data] retain];
        self.downloadProgressLabel.text = @"Downloading...";
    } else {
        // oh noes!
    }
}

- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [receivedData setLength:0]; 
}

- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {   
    [receivedData appendData:data]; 
    int kb = [receivedData length] / 1024;
    self.downloadProgressLabel.text = [NSString stringWithFormat:@"Downloaded\n%d kB", kb];
}

connectionWithRequest does indeed run in it's own thread - no need for you to worry about this. In fact it must be started from the main thread. Check out the NSUrlConnection doc for more info.

thomax
More than lock the UI it delays the events chain until the download is finished. All the responders I touch responds after the download.
Espuz
I try your test with the label and it isn't be updated until end of download :(
Espuz
+1  A: 
+ (id)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate];

This method should create an asynchronous-request (that means that it runs in the background and it doesn't block the UI). You should check if there's another class/method in your file that blocks the UI (for example NSData's '+ (NSData *)dataWithContentsOfURL:(NSURL *)URL').

Tim van Elsloo
0 occurrences of "dataWithContentsOfURL" in my project. Although, do you know what are the selectors that blocks UI? Maybe I have one of these in my code.
Espuz
Hmm, is the UI still being blocked after de data has been load (didFinishLoading-method has been called)?
Tim van Elsloo