Objective C Threading

Associate
Joined
25 Feb 2007
Posts
905
Location
Midlands
Hi,

I'm trying to create an iPhone app that pulls data from a web services as a JSON string, however when I do this, I sometimes get this error:

"Obtaining the web lock from a thread other than the main thread or the web thread. UIKit should not be called from a secondary thread."

I understand what the error is telling me (I think), but don't know how to fix it!

Here's my code I'm using to get the JSON data, which runs on the press of a button after the user fills out some required info:

Code:
if(self.textbox.text){
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        dispatch_async(queue, ^{
            NSError *error = nil;
            NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"URL-TO-WEB-SERVICE"]];
            NSString *json = [NSString stringWithContentsOfURL:url
                                                      encoding:NSASCIIStringEncoding
                                                         error:&error];

Any advice?

Cheers! :D
 
Well I think it's telling me that I can't update the UI from anything other than the main thread, but I don't think I'm updating the UI at all...

Yes I did miss out the last bit of code!

Code:
            if(!error) {
                NSData *jsonData = [json dataUsingEncoding:NSASCIIStringEncoding];
                
                [self performSelectorOnMainThread:@selector(fetchedData:) 
                                       withObject:jsonData waitUntilDone:YES];
                
            }
                
        });

I was setting the values of some variables to the the values of text boxes in the interface, which were then used as query parameters when building the url to get the JSON string - is this the issue?

I've since moved that bit out of the dispatch_async code block, so I'm creating the url with parameters before than, and then passing it in as a local variable.

Now I'm getting a different error:

Error Domain=NSCocoaErrorDomain Code=256 "The operation couldn’t be completed.

Thanks!
 
OK, slightly related (rather than opening a new thread).

I've changed dispatch_async to dispatch_sync as it was loading the view before the data had been downloaded.

Dispatch_sync gives the desired effect in that the user can't progress until all the data has been downloaded, however it now looks like my app hangs for a few seconds.

How can I implement a loading bar/graphic to show the user that something is actually happening whilst the data is downloaded?
 
I don't think it really matters, the user doesn't 'know' that a file is being downloaded, just that it's fetching their data, so a spinny wheel would do :p

I'll take a look at your link, looks useful! Cheers.
 
So if I use NSURLConnection I don't need to worry about GCD at all?

As you've guessed, I'm very much the beginner, however my choice of multithreading wasn't through choice, more that it seemed to be 'the right way to do things'. If I could I'd avoid it, as I don't think my app is demanding enough to require it.

Don't worry about being critical, I welcome it :D

So NSURLConnection will handle the downloading of the JSON string and I can call my parser and show some sort of loading graphic at the same time?
 
Hi Tillus,

Only just seen your response to this - thanks!

In the meantime I've implemented NSURLConnection and it works very well, I have it updating the progress bar however I no longer have the 'wait' before next view is loaded.

I think this is because I have the next view connected as a 'segue' on the button press in my storyboard, so it loads the next view and fires NSURLConnection. I think I need to remove the 'segue' and have it load the next view on connectionDidFinishLoading. Is that correct? Any pointers on how I'd implement that?

Cheers!
 
Back
Top Bottom