Question

In my app, the root view controller acquires information from the internet, parses it, and displays it in viewDidAppear. I am using this method because my app in embedded in a UINavigationController and this way the root view controller will reload its data when the user presses the back button and pops to the root view.

When this occurs, it takes some time for the information from the internet to be acquired and displayed. During this time, if the user clicks a button to move to a different view, the button action will not occur until the view controller has completed its process of acquiring the web data.

How can I make it so that the buttons will override the other processes and immediately switch the view? Is this safe? Thanks in advance.

Edit

Here's an example of a portion where I take the information off of the site (My app parses the HTML).

NSURL *siteURL = [NSURL URLWithString:@"http://www.ridgefield.org/ajax/dist/emergency-announcements"];
NSError *error;
NSString *source = [NSString stringWithContentsOfURL:siteURL 
                                            encoding:NSUTF8StringEncoding
                                               error:&error];
Was it helpful?

Solution

This is where Apple folks would hound, "don't block the main thread!".

The primary suggestion for this kind of workflow is to use a separate thread (read: queue) for loading data from the web. Then the worker who completes the load can set some property on your view controller, and inside that setter is where the UI should be updated. Remember to call the setter back on the main thread.

There are several ways to skin the concurrency cat, but the answer to this particular question leaves them out of scope. The short answer is to not do the load in the main thread, and that should lead you to the right place.

OTHER TIPS

The NSString method stringWithContentsOfURL is synchronous and will block your main thread.

Instead of using background threads to solve the problem, you can use asynchronous URL requests. This does not block the user interface because a delegate protocol is used to let you know when the request is complete. For example:

        NSURL *url = [NSURL URLWithString:@""http://www.ridgefield.org/ajax/dist/emergency-announcements""];
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        NSURLConnection* theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];       

And then some of your delegate methods are:

-(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)theResponse
{
    // create received data array
    _receivedData = [[NSMutableData alloc] init]; 
}

-(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)theData
{
    // append to received data.
    [_receivedData appendData:theData];
}


-(void)connectionDidFinishLoading:(NSURLConnection*)connection
{
    // now the connection is complete
    NSString* strResult = [[NSString alloc] initWithData: _receivedData encoding:NSUTF8StringEncoding];

    // now parse strResult
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top