iOS dispatch_async and NSURLConnection delegate functions not being called

12,526

Solution 1

Someone from iphonedevsdk.com forum answered this for me:

http://www.iphonedevsdk.com/forum/iphone-sdk-development/97415-dispatch_async-nsurlconnection.html

The answer was to use:

 [self performSelectorOnMainThread:@selector(getPrices) withObject:Nil waitUntilDone:NO];

Solution 2

I have started a SO post which shows how to use the NSURLConnection with dispatch_async and configure the NSRunLoop

NSURLConnection blocking wrapper implemented with semaphores

The piece of code that you would be interested in is:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSURLRequest* request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
    [NSURLConnection connectionWithRequest:request delegate:self];

    while(!self.finished) {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
});

and in the connectionDidFinishLoading, set finished to YES:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    self.finish = YES;
}
Share:
12,526
Pete
Author by

Pete

I'm a web developer/full stack developer/programmer/nerd/internet person what ever you want to call me, I currently make websites and APIs, with CFML(ACF and Lucee), Node.js and Vue.js. I've done some Native iOS and Phonegap/Cordova iOS and Android work in the past. I'll can fix a computer, manage servers, monitor logs, build databases, optimize queries, shrink download sizes, speed up sites, write back end code, build front end interfaces, analyze user behaviours, get conversions and leads... just don't ask me to design anything. I'm a father, husband, 1st degree taekwondo black belt and Grade 2 guitarist who likes drawing, driving, gaming and all the usual sci-fi nerd stuff.

Updated on June 25, 2022

Comments

  • Pete
    Pete almost 2 years

    I've edited this post to make it simpler to read, I think.

    I need to call an NSUrlConnection after I've finished doing some intensive string manipulation in a dispatch_async block.

    The URL I call has got .htaccess authentication on it, so I can't use a synchronous connection.

    But the NSURLConnection delegate methods are not being called. I know the URL loads after about 5 seconds in the browser, and I've tested the code with a simple URL with no authentication and it makes no difference.

    What is stopping the delegate methods being called?

    This function does some string manipulation stuff, and takes a while to finish:

    - (void)performSearch {
    
        // set some defaults and work out if it is a valid search, setting bSearchOk
    
        if (bSearchOk) {
    
            // update some interface elements
            self.msgBox.text = @"Translating...";            
            self.plateInput.enabled = NO;
            self.searchProgress.hidden = NO;
    
            dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
                // create a new search
                Search *oPlateSearch = [[Search alloc] initWithTerm:thisTerm];
    
                // ...
                // perform search... this calls a variety of slow and intensive functions
                // ...
    
                self.aFinalPlates = [oPlateSearch.aValidated copy];
                self.aCurrentPlates = [oPlateSearch.aFinals copy];        
    
                dispatch_async( dispatch_get_main_queue(), ^{                 
                    [oPlateSearch release];              
    
                    // make ajax call to check if plates can be bought
                    [self getPrices];                 
                });
            });
    
        } else {
            // hide results
            self.searchResults.hidden = YES;
        }
    
    }
    

    And this is the one called towards the end of the block above

    /* call to get plate availability and prices */
    -(void) getPrices {
        // set return message
        self.msgBox.text = @"Getting prices and availability";
    
        // ...
        // then I build my strRequest var, which is a valid working URL
        // ...
    
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:strRequest]];
    
        NSURLConnection *loginConnection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
    
        NSLog('This will get logged');
    
        if(loginConnection) {
            NSLog('This will also get logged');
            self.jsonSearchResponse = [[[NSMutableData data] retain] autorelease];
            NSLog('And this will get logged, so it's not throwing errors');
        } else {
            NSLog(@"Failed to get search results");
        }
    }
    

    Update: I've tried this as well, as it was an accepted in answer on another similar question, but it hasn't worked:

    NSURLConnection *loginConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    [loginConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
    [loginConnection start];
    

    Based on this question: Why NSURLConnection delegate methods don't get called, when using the global dispatch queue?