Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
($1.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 01-22-2012, 01:46 PM   #1 (permalink)
Registered Member
 
Join Date: Jan 2012
Posts: 3
WillshawMedia is on a distinguished road
Default dispatch_async and NSURLConnection

I'm really struggling with an app I'm writing at the moment.

I've got some intense string manipulation, which I'm performing inside a dispatch_async block.

At the end of the block I've got a dispatch_async(dispatch_get_main_queue()) block, which calls a custom function: getPrices();

Inside getPrices() I use an NSURLConnection. The delegate methods are not being called, my connection is made, but I don't get a fail, success, authentication challenge, anything at all.

The code looks like this:

Code:
- (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 getPrices()

Code:
/* 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 startImmediately:NO];
[loginConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[loginConnection start];

    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");
    }
}
Any ideas what I'm doing wrong?
WillshawMedia is offline   Reply With Quote
Old 01-22-2012, 01:53 PM   #2 (permalink)
Cocoa Junkie
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 6,003
Duncan C has a spectacular aura about
Default

Quote:
Originally Posted by WillshawMedia View Post
I'm really struggling with an app I'm writing at the moment.

I've got some intense string manipulation, which I'm performing inside a dispatch_async block.

At the end of the block I've got a dispatch_async(dispatch_get_main_queue()) block, which calls a custom function: getPrices();

Inside getPrices() I use an NSURLConnection. The delegate methods are not being called, my connection is made, but I don't get a fail, success, authentication challenge, anything at all.

The code looks like this:

Code:
- (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 getPrices()

Code:
/* 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 startImmediately:NO];
[loginConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[loginConnection start];

    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");
    }
}
Any ideas what I'm doing wrong?
Call your getPrices method using preformSelectorOnMainThread.

Make getPrices simply call [connection start] without using scheduleInRunLoop.

Set your object to be the delegate of the connection, so you get callbacks as the download progresses.
__________________
Regards,

Duncan C
WareTo

Check out our apps in the Apple App store


Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.

See this tutorial on using UIView animations and layer animations:

See this thread on generating random, non-repeating text

Check out a very cool Macintosh Kaleidoscopes app called ScopeWorks that we released to the Mac App store.
Duncan C is offline   Reply With Quote
Old 01-23-2012, 01:58 AM   #3 (permalink)
Registered Member
 
Join Date: Jan 2012
Posts: 3
WillshawMedia is on a distinguished road
Default

Quote:
Originally Posted by Duncan C View Post
Call your getPrices method using preformSelectorOnMainThread.

Make getPrices simply call [connection start] without using scheduleInRunLoop.

Set your object to be the delegate of the connection, so you get callbacks as the download progresses.
I don't think I fully understand the documentation for performSelectorOnMainThread.

I've tried this:

Code:
 [self performSelectorOnMainThread:getPrices withObject:Nil waitUntilDone:NO];
But I'm getting the error: "Use of undeclared identifier getPrices". The docs say that parameter should be a "selector that identifies the method to invoke" and I want to invoke getPrices.

I thought delegate:self was already setting the delegate to be the object calling the method? Is that not right?
WillshawMedia is offline   Reply With Quote
Old 01-23-2012, 03:42 AM   #4 (permalink)
Registered Member
 
apatsufas's Avatar
 
Join Date: Jan 2011
Location: Thessaloniki, Greece
Posts: 121
apatsufas is on a distinguished road
Default

The appropriate syntax for performSelectorOnMainThread is

Code:
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
in your case that would be

Code:
 [self performSelectorOnMainThread:@selector(getPrices) withObject:Nil waitUntilDone:NO];
__________________
SQLed - Your Database Manager on the go

iAZConverter - Converts everything from A to Z
apatsufas is offline   Reply With Quote
Old 01-27-2012, 06:57 AM   #5 (permalink)
Registered Member
 
Join Date: Jan 2012
Posts: 3
WillshawMedia is on a distinguished road
Default

Quote:
Originally Posted by apatsufas View Post
in your case that would be

Code:
 [self performSelectorOnMainThread:@selector(getPrices) withObject:Nil waitUntilDone:NO];
That fixed it, that was perfect. Thanks to both of you for helping!
WillshawMedia is offline   Reply With Quote
Reply

Bookmarks

Tags
dispatch_async, nsurlconnection

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 389
9 members and 380 guests
7twenty7, Atatator, FrankWeller, glenn_sayers, iphonedevshani, MAMN84, QuantumDoja, tim0504, VinceYuan
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,674
Threads: 94,122
Posts: 402,907
Top Poster: BrianSlick (7,990)
Welcome to our newest member, Atatator
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 05:47 AM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0