0

I can't seem to get a Delegate callback to work when I thread my code. I am trying to call a remote server using NSURLConnection to get an access_token. The access_token is received in connection:didReceiveResponse: delegate. This is not a problem until I thread it. I thought I was passing the correct objects for my delegates, but it does not reach connection:didReceiveResponse:

Can anyone see why connection:didReceiveResponse: in LoginViewController does not get called when I thread the call? Thanks.

LoginViewController.m

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSString *access_token = [self getTokenFromResponse: response]; 
    [self.delegate didGetAccessToken:access_token]; 
}

- (void)fetchAccessTokenNoUI
{
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: @"www.mysite.com"]];   
    [NSURLConnection connectionWithRequest:request delegate:self];
} 

AccessToken.h

@interface AccessToken : NSObject
@property (atomic, strong) LoginViewController *loginViewController; // doing this to try to keep it persistent
- (void) fetchAccessTokenWithDelegate: (id <LoginDelegate>)delegate;
@end

AccessToken.m

- (void) fetchAccessTokenWithDelegate: (id < LoginDelegate >)delegate
{
    dispatch_queue_t downloadQueue = dispatch_queue_create("Fetch access_token queue", NULL);
    dispatch_async(downloadQueue, ^ {
        // this works fine if I don't do it in a queue
        self.loginViewController = [[LoginViewController alloc] init];
        self.loginViewController.delegate = delegate;
        [self.loginViewController fetchAccessTokenNoUI];

    });
    dispatch_release(downloadQueue);
}

CallingClass.m

- (void)didGetAccessToken:(NSString *)access_token
{
    if (!access_token)
    {
        LoginViewController *userProfileViewController = [[LoginViewController alloc] init];
        userProfileViewController.delegate = self;
        [self.navigationController pushViewController:userProfileViewController animated:YES];
    }
}
- (IBAction)favourite:(id)sender 
{
    AccessToken *accessToken = [[AccessToken alloc] init];
    [accessToken fetchAccessTokenWithDelegate:self];

}
Raymond
  • 105
  • 1
  • 3
  • 13

2 Answers2

0

Have you put stubs to implement the required protocol methods,

-(void)connectionDidFinishLoading:(NSURLConnection *)connection;
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;

Because I had a similar problem which went away after implementing them.

Vili
  • 1,599
  • 15
  • 40
vellvisher
  • 484
  • 4
  • 12
  • Just tried it but no luck. I even made them public in .h and still didn't work. – Raymond Jun 19 '12 at 18:26
  • `didReceiveResponse` this function is not called at all? – vellvisher Jun 20 '12 at 02:35
  • No. didReceiveResponse does not get called. It would have been called from connection:didReceiveResponse: which isn't even called. Inspired by your commented, I tried calling didReceiveResponse from [LoginViewController fetchAccessTokenNoUI] and it worked so I believe that means the delegate is properly set. – Raymond Jun 20 '12 at 04:04
0

So after some more research, I found the solution.

I don't actually need AccessToken.h/m. I thought that the NSURLConnection call would block my UI thread. But NSURLConnection connectionWithRequest:delegate: is automatically run in a separate thread.

So all I have to do is delete AccessToken.h and AccessToken.m. Then, in CallingClass.m, I change favourte: to

- (IBAction)favourite:(id)sender 
{
    LoginViewController *loginViewController = [[LoginViewController alloc] init];
    [loginViewController fetchAccessTokenWithDelegate:self];

}

That's it! Don't need to dispatch_queue_t at all.

Raymond
  • 105
  • 1
  • 3
  • 13