Problems getting NSURLConnection to work

  • Greetings and Salutations,
    I've setup a class as a delegate for NSURLConnection, though when I
    create the NSURLConnection and provide it a delegate (self), the
    delegate methods don't get called. I know they don't get called as
    I've put in NSLog() statements and these statements don't get displayed.

    Is there something I'm missing?

    Follows is the code from the class implementation file:

    Thanks,
    Matthew Delves

    ----------------
    // Instance methods
    - (id) initWithUrl:(NSURL *)aUrl
    {
    /*
        NSURLConnection why won't you work?
        I follow your documentation, why won't you work?
        I remove garbage collection, why won't you work?
        I change the thread you run on, why won't you work?
        NSURLConnection why won't you work?
        */

    url = [aUrl copy]; // copy the url
    [url retain];
    NSLog(@"%@", url);
    responseString = nil;
    responseCode = 0.0;
    document = nil;
    urlConnection = nil;
    urlRequest = nil;
    urlResponse = nil;
    urlData = nil;

    urlRequest = [[NSMutableURLRequest alloc] initWithURL:url
                                                 cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                             timeoutInterval:60.0];

    [urlRequest retain];
    [urlRequest setMainDocumentURL:url];
    [urlRequest setURL:url];

    if([NSURLConnection canHandleRequest:urlRequest])
      urlConnection = [NSURLConnection connectionWithRequest:urlRequest
                                                         delegate:self];

    if(urlConnection) {
      [urlConnection retain];
      urlData = [[NSMutableData alloc] init];
      [urlConnection start];
      [urlData retain];
    } else {
      finishedDownload = YES;
      failedDownload = YES;
      NSLog(@"urlConnection has become a pointer to nil");
    }

    failedDownload = NO;
    finishedDownload = NO;
    downloading = NO;
    document = nil;

    NSLog(@"end of fetcher init");

    if(!urlConnection)
      NSLog(@"blah!");

    return self;
    }

    - (void) dealloc
    {

    [urlConnection release];
    urlConnection = nil;

    [urlRequest release];
    urlRequest = nil;

    [urlResponse release];
    urlResponse = nil;

    [responseString release];
    responseString = nil;

    [document release];
    document = nil;

    [urlData release];
    urlData = nil;

    [url release];
    url = nil;

    [super dealloc];
    }

    // NSURLConnection delegate methods
    - (void)connection:(NSURLConnection *)connection
    didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge
    *)challenge
    {
    NSLog(@"cancel of authentication request");
    }

    - (void)connection:(NSURLConnection *)connection didFailWithError:
    (NSError *)error
    {
    NSLog(@"Connection failed! Error - %@ %@",
              [error localizedDescription],
              [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
    failedDownload = YES;
    downloading = NO;
    [urlRequest release];
    [urlResponse release];
    [urlConnection release];
    }

    - (void)connection:(NSURLConnection *)connection
    didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge
    *)challenge
    {
    NSLog(@"Authentication request received");
    }

    - (void)connection:(NSURLConnection *)connection didReceiveData:
    (NSData *)data
    {
    NSLog(@"received data");
    if(!urlData){
      urlData = [[NSMutableData alloc] init];
      [urlData setLength:0];
    }

    [urlData appendData:data];
    }

    - (void)connection:(NSURLConnection *)connection didReceiveResponse:
    (NSURLResponse *)response
    {
    NSLog(@"Response received");
    downloading = YES;
    [urlData setLength:0];
    }

    - (NSCachedURLResponse *)connection:(NSURLConnection *)connection
    willCacheResponse:(NSCachedURLResponse *)cachedResponse
    {
    NSCachedURLResponse *newCachedResponse=cachedResponse;
    NSDictionary *newUserInfo;

    newUserInfo=[NSDictionary dictionaryWithObject:[NSCalendarDate date]
              forKey:@"Cached Date"];

    newCachedResponse=[[[NSCachedURLResponse alloc] initWithResponse:
    [cachedResponse response]
                    data:[cachedResponse data]
                  userInfo:newUserInfo
                                                         storagePolicy:[cachedResponse storagePolicy]]
    autorelease];

    return newCachedResponse;
    }

    - (NSURLRequest *)connection:(NSURLConnection *)connection
                willSendRequest:(NSURLRequest *)aRequest
      redirectResponse:(NSURLResponse *)redirectResponse
    {
        NSURLRequest *newRequest = aRequest;

        if (redirectResponse) {
            newRequest=nil;
        }
        return newRequest;
    }

    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
    finishedDownload = YES;
    downloading = NO;
    NSLog(@"Finished downloading file", url);
    NSError *err= [[NSError alloc] init];
    document = [[NSXMLDocument alloc] initWithData:urlData
                                             options:(NSXMLNodePreserveWhitespace|
    NSXMLNodePreserveCDATA)
                                                error:&err];
    [document retain];
    [urlConnection release];
    [urlRequest release];
    [urlResponse release];
    }

    ---------------
  • On Feb 8, 2008, at 10:19 PM, Matthew Delves wrote:
    > I've setup a class as a delegate for NSURLConnection, though when I
    > create the NSURLConnection and provide it a delegate (self), the
    > delegate methods don't get called. I know they don't get called as
    > I've put in NSLog() statements and these statements don't get
    > displayed.
    >
    > Is there something I'm missing?

    Why aren't you setting self to [super init] or the superclass's
    initializer in the -initWithURL: method? Also, you're over-retaining
    some memory. Are you using GC?

    Nick Zitzmann
    <http://www.chronosnet.com/>
  • On Feb 9, 2008, at 07:19, Matthew Delves wrote:

    > I've setup a class as a delegate for NSURLConnection, though when I
    > create the NSURLConnection and provide it a delegate (self), the
    > delegate methods don't get called. I know they don't get called as
    > I've put in NSLog() statements and these statements don't get
    > displayed.
    >
    > Is there something I'm missing?
    >
    > Follows is the code from the class implementation file:

    > - (id) initWithUrl:(NSURL *)aUrl
    > {
    > /*
    > NSURLConnection why won't you work?
    > I follow your documentation, why won't you work?
    > I remove garbage collection, why won't you work?
    > I change the thread you run on, why won't you work?

    On which thread do you run this? It works fine on the main thread.

    > NSURLConnection why won't you work?
    > */
    >
    > url = [aUrl copy]; // copy the url

    Why copy the url?

    > [url retain];

    And then retain it!?

    > NSLog(@"%@", url);

    Can you access this url with a browser?

    > responseString = nil;
    > responseCode = 0.0;

    responseCode is a float?!

    > document = nil;
    > urlConnection = nil;
    > urlRequest = nil;
    > urlResponse = nil;
    > urlData = nil;
    >
    > urlRequest = [[NSMutableURLRequest alloc] initWithURL:url
    > cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
    > timeoutInterval:60.0];
    >
    > [urlRequest retain];

    Why retain an object created with alloc?

    > [urlRequest setMainDocumentURL:url];
    > [urlRequest setURL:url];

    Why do you set the url again?

    >
    > if([NSURLConnection canHandleRequest:urlRequest])
    > urlConnection = [NSURLConnection connectionWithRequest:urlRequest
    > delegate:self];
    >
    > if(urlConnection) {
    > [urlConnection retain];

    If you want to retain the object, why not create it with –
    initWithRequest:delegate:?

    > urlData = [[NSMutableData alloc] init];
    > [urlConnection start];

    start? NSURLConnection does not respond to this. The connection
    starts when you create it.

    I guess that at this point an exception is raised and your
    initializer fails. This is why you don't get any notifications.

    Best Regards,

    Nir Soffer
  • On Feb 9, 2008, at 15:14, Nir Soffer wrote:

    >> [urlConnection start];
    >
    > start? NSURLConnection does not respond to this. The connection
    > starts when you create it.
    >
    > I guess that at this point an exception is raised and your
    > initializer fails. This is why you don't get any notifications.

    I see that -start was added in 10.5, so you don't get an exception
    here. Looks like not calling [super init] is the issue.

    Best Regards,

    Nir Soffer
  • On 10/02/2008, at 12:31 AM, Nir Soffer wrote:

    >
    > On Feb 9, 2008, at 15:14, Nir Soffer wrote:
    >
    >>> [urlConnection start];
    >>
    >> start? NSURLConnection does not respond to this. The connection
    >> starts when you create it.
    >>
    >> I guess that at this point an exception is raised and your
    >> initializer fails. This is why you don't get any notifications.
    >
    > I see that -start was added in 10.5, so you don't get an exception
    > here. Looks like not calling [super init] is the issue.
    >

    Unfortunately not. I placed in a call to [super init] though that made
    no difference.

    With the comments from your previous email, I have been scratching my
    head over a lot of it including using an NSMutableURLRequest and
    setting the url of it a second time. As far as threads are concerned,
    I've run in on the main thread and a seperate thread and get the same
    results.

    Any suggestions would be greatly appreciated.

    Thanks,
    Matthew Delves
  • on 2/9/08 7:23 AM, <cocoa-dev-request...> at
    <cocoa-dev-request...> wrote:

    > Unfortunately not. I placed in a call to [super init] though that made
    > no difference.
    >
    > With the comments from your previous email, I have been scratching my
    > head over a lot of it including using an NSMutableURLRequest and
    > setting the url of it a second time. As far as threads are concerned,
    > I've run in on the main thread and a seperate thread and get the same
    > results.
    >
    > Any suggestions would be greatly appreciated.

    Do what I did the day before yesterday when I used NSURLConnection for the
    first time, help yourself to Apple code that works perfectly, at least it
    did for me immediately.

    http://developer.apple.com/samplecode/LSMSmartCategorizer/listing17.html

    If it does work for you as well, then go through and try and sort out what
    the significant difference is with your code, if it doesn't ... then your
    real problem is probably not NSURLConnection related.

    --
    Alex Curylo -- <alex...> -- http://www.alexcurylo.com/

    "The reason I didn't go into the clouds was I saw you fly in first...
    I'm not flying into any cloud with a crazy Curylo brother in it."
        -- Jim Reich
  • On Feb 9, 2008, at 17:08, Matthew Delves wrote:

    > Unfortunately not. I placed in a call to [super init] though that
    > made no difference.
    >
    > With the comments from your previous email, I have been scratching
    > my head over a lot of it including using an NSMutableURLRequest and
    > setting the url of it a second time. As far as threads are
    > concerned, I've run in on the main thread and a seperate thread and
    > get the same results.
    >
    > Any suggestions would be greatly appreciated.

    This is what I would:

    1. Create a new cocoa app for testing, and setup an application delegate

    2. Add this minimal code in the application delegate:

    /* AppDelegate.h */

    #import <Cocoa/Cocoa.h>

    @interface AppDelegate : NSObject
    {
    NSURLConnection *connection;
    }
    @end

    /* AppDelegate.m */

    #import "AppDelegate.h"

    @implementation AppDelegate

    - (void)applicationDidFinishLaunching:(NSNotification *)notification;
    {
        NSURL *url = [NSURL URLWithString:@"http://www.apple.com/"];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

        connection = [[NSURLConnection alloc] initWithRequest:request
                                                      delegate:self];
        if (connection == nil) {
            NSLog(@"cannot create connection");
            return;
        }
    }

    -(void)connection:(NSURLConnection *)sender didReceiveResponse:
    (NSURLResponse *)response;
    {
        NSLog(@"received response");
    }

    @end

    3. Compile and test

    4. Add more features one by one: save received data, handle
    redirects, caching, etc.

    5. When you finish, integrate with your app.

    Best Regards,

    Nir Soffer
  • On 8 Feb '08, at 9:19 PM, Matthew Delves wrote:

    > I've setup a class as a delegate for NSURLConnection, though when I
    > create the NSURLConnection and provide it a delegate (self), the
    > delegate methods don't get called. I know they don't get called as
    > I've put in NSLog() statements and these statements don't get
    > displayed.

    My guess would be that, due to some bug elsewhere in your code, your
    object is getting dealloced immediately after it's created. That will
    cause its -dealloc method to release the URLConnection, which will
    stop it. To test this hypothesis, put a breakpoint or NSLog call in
    your dealloc method.

    (Speaking of refcounting — I noticed that both urlRequest and urlData
    are over-retained: they're created with alloc/init, but then -retain
    is called again, creating two references.)

    —Jens
  • So right of the bat a few things (just to get in the habit of)..

    1.) Before you do any of your code you need the:

    self = [super init]

    if (self != nil)
    ...

    2.) Why copy URL? Why not just retain if you are keeping it around?
    3.) Copy will call alloc init.. NO need to reatain again.
    4.) Your URLRequest is retained too many times. Do retain if using
    alloc init.

    Are you getting a valid URL connection back?

    On Feb 8, 2008, at 9:19 PM, Matthew Delves wrote:

    > Greetings and Salutations,
    > I've setup a class as a delegate for NSURLConnection, though when I
    > create the NSURLConnection and provide it a delegate (self), the
    > delegate methods don't get called. I know they don't get called as
    > I've put in NSLog() statements and these statements don't get
    > displayed.
    >
    > Is there something I'm missing?
    >
    > Follows is the code from the class implementation file:
    >
    > Thanks,
    > Matthew Delves
    >
    > ----------------
    > // Instance methods
    > - (id) initWithUrl:(NSURL *)aUrl
    > {
    > /*
    > NSURLConnection why won't you work?
    > I follow your documentation, why won't you work?
    > I remove garbage collection, why won't you work?
    > I change the thread you run on, why won't you work?
    > NSURLConnection why won't you work?
    > */
    >
    > url = [aUrl copy]; // copy the url
    > [url retain];
    > NSLog(@"%@", url);
    > responseString = nil;
    > responseCode = 0.0;
    > document = nil;
    > urlConnection = nil;
    > urlRequest = nil;
    > urlResponse = nil;
    > urlData = nil;
    >
    > urlRequest = [[NSMutableURLRequest alloc] initWithURL:url
    > cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
    > timeoutInterval:60.0];
    >
    > [urlRequest retain];
    > [urlRequest setMainDocumentURL:url];
    > [urlRequest setURL:url];
    >
    > if([NSURLConnection canHandleRequest:urlRequest])
    > urlConnection = [NSURLConnection connectionWithRequest:urlRequest
    > delegate:self];
    >
    > if(urlConnection) {
    > [urlConnection retain];
    > urlData = [[NSMutableData alloc] init];
    > [urlConnection start];
    > [urlData retain];
    > } else {
    > finishedDownload = YES;
    > failedDownload = YES;
    > NSLog(@"urlConnection has become a pointer to nil");
    > }
    >
    > failedDownload = NO;
    > finishedDownload = NO;
    > downloading = NO;
    > document = nil;
    >
    > NSLog(@"end of fetcher init");
    >
    > if(!urlConnection)
    > NSLog(@"blah!");
    >
    > return self;
    > }
    >
    > - (void) dealloc
    > {
    >
    > [urlConnection release];
    > urlConnection = nil;
    >
    > [urlRequest release];
    > urlRequest = nil;
    >
    > [urlResponse release];
    > urlResponse = nil;
    >
    > [responseString release];
    > responseString = nil;
    >
    > [document release];
    > document = nil;
    >
    > [urlData release];
    > urlData = nil;
    >
    > [url release];
    > url = nil;
    >
    > [super dealloc];
    > }
    >
    >
    > // NSURLConnection delegate methods
    > - (void)connection:(NSURLConnection *)connection
    > didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge
    > *)challenge
    > {
    > NSLog(@"cancel of authentication request");
    > }
    >
    > - (void)connection:(NSURLConnection *)connection didFailWithError:
    > (NSError *)error
    > {
    > NSLog(@"Connection failed! Error - %@ %@",
    > [error localizedDescription],
    > [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
    > failedDownload = YES;
    > downloading = NO;
    > [urlRequest release];
    > [urlResponse release];
    > [urlConnection release];
    > }
    >
    > - (void)connection:(NSURLConnection *)connection
    > didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge
    > *)challenge
    > {
    > NSLog(@"Authentication request received");
    > }
    >
    > - (void)connection:(NSURLConnection *)connection didReceiveData:
    > (NSData *)data
    > {
    > NSLog(@"received data");
    > if(!urlData){
    > urlData = [[NSMutableData alloc] init];
    > [urlData setLength:0];
    > }
    >
    > [urlData appendData:data];
    > }
    >
    > - (void)connection:(NSURLConnection *)connection didReceiveResponse:
    > (NSURLResponse *)response
    > {
    > NSLog(@"Response received");
    > downloading = YES;
    > [urlData setLength:0];
    > }
    >
    > - (NSCachedURLResponse *)connection:(NSURLConnection *)connection
    > willCacheResponse:(NSCachedURLResponse *)cachedResponse
    > {
    > NSCachedURLResponse *newCachedResponse=cachedResponse;
    > NSDictionary *newUserInfo;
    >
    > newUserInfo=[NSDictionary dictionaryWithObject:[NSCalendarDate date]
    > forKey:@"Cached Date"];
    >
    > newCachedResponse=[[[NSCachedURLResponse alloc] initWithResponse:
    > [cachedResponse response]
    > data:[cachedResponse data]
    > userInfo:newUserInfo
    > storagePolicy:[cachedResponse storagePolicy]]
    > autorelease];
    >
    > return newCachedResponse;
    > }
    >
    > - (NSURLRequest *)connection:(NSURLConnection *)connection
    > willSendRequest:(NSURLRequest *)aRequest
    > redirectResponse:(NSURLResponse *)redirectResponse
    > {
    > NSURLRequest *newRequest = aRequest;
    >
    > if (redirectResponse) {
    > newRequest=nil;
    > }
    > return newRequest;
    > }
    >
    > - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    > {
    > finishedDownload = YES;
    > downloading = NO;
    > NSLog(@"Finished downloading file", url);
    > NSError *err= [[NSError alloc] init];
    > document = [[NSXMLDocument alloc] initWithData:urlData
    > options:(NSXMLNodePreserveWhitespace|
    > NSXMLNodePreserveCDATA)
    > error:&err];
    > [document retain];
    > [urlConnection release];
    > [urlRequest release];
    > [urlResponse release];
    > }
    >
    > ---------------