Re: NSURLConnection failing [SOLVED]

  • On Thu, Feb 21, 2008 at 9:23 PM, Doug Penny <doug.penny...> wrote:
    > I am trying to use NSURLConnection to fetch a few small images (like
    > 10k) from various websites.  The connections are established and then
    > the connection:willSendRequest:redirectResponse: delegate method is
    > called and it freezes.  It never times out that I know of, at least
    > the connection:didFailWithError: delegate is never called.  So now for
    > the crazy part... sometimes the code works fine and all of the images
    > are retrieved.  I have tested this with several different sites and it
    > seems to be fairly random.  I have tried different caching policies as
    > well with no change.  If it fails, it always seems to fail after the
    > redirect is received.  I am running this on Leopard with GC enabled.
    > Below is the code I am using, I removed all the log messages I was
    > using for debugging.  If anyone has any ideas they would be greatly
    > appreciated.
    >
    >
    > NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL
    > URLWithString:imageURL]
    >
    > cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
    >
    > timeoutInterval:30.0];
    >
    > NSURLConnection *imageConnection = [[NSURLConnection alloc]
    > initWithRequest:request
    >
    > delegate:self];
    >
    > if (!imageConnection) {
    > NSLog(@"A problem was encountered while trying to download an
    > image from %@", imageURL);
    > }
    >
    >
    > ----------------delegate methods-----------------
    >
    > - (void)connection:(NSURLConnection *)connection
    > didReceiveResponse:(NSURLResponse *)response
    > {
    > [receivedData setLength:0];
    > }
    >
    > - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    > {
    > [receivedData appendData:data];
    > }
    >
    > - (NSURLRequest *)connection:(NSURLConnection *)connection
    > willSendRequest:(NSURLRequest *)request
    > redirectResponse:(NSURLResponse *)redirectResponse
    > {
    > return request;
    > }
    >
    > - (void)connection:(NSURLConnection *)connection
    > didFailWithError:(NSError *)error
    > {
    > NSLog(@"Error: %@", [error localizedDescription]);
    > }
    >
    > - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    > {
    > image = [[NSImage alloc] initWithData:receivedData];
    > if (!image || ![image isValid]) {
    > image = [NSImage imageNamed:@"missingImage.tiff"];
    > }
    > }
    >
    >
    >
    > -Doug
    >

    Turns out garbage collection was doing me in.  When the
    NSURLConnection object was hanging out waiting for a response, it
    would get collected.  To work around this, after creating the
    NSURLConnection object I just stick it in a NSMutableSet.  When the
    delegate gets the -connectionDidFinishLoading: message I remove the
    connection object from the set.  Works great now.

    Doug
  • On 2008 Feb, 25, at 8:18, Doug Penny wrote:

    > Turns out garbage collection was doing me in.  When the
    > NSURLConnection object was hanging out waiting for a response, it
    > would get collected.

    I'd call that a pretty serious garbage-collection bug in
    NSURLConnection!  Unless you'd sent it a -cancel, it ain't garbage.  I
    sure hope that bugs like this get reported and fixed before I try and
    use GC!

    > To work around this, after creating the
    > NSURLConnection object I just stick it in a NSMutableSet.  When the
    > delegate gets the -connectionDidFinishLoading: message I remove the
    > connection object from the set.  Works great now.

    Yep, that would work-around it.
  • On Tue, Feb 26, 2008 at 5:55 PM, Jerry Krinock <jerry...> wrote:

    > I'd call that a pretty serious garbage-collection bug in
    > NSURLConnection!  Unless you'd sent it a -cancel, it ain't garbage.

    Unless you keep a strong reference to it, it *is* garbage.

    > On 2008 Feb, 25, at 8:18, Doug Penny wrote:
    >> To work around this, after creating the
    >> NSURLConnection object I just stick it in a NSMutableSet.  When the
    >> delegate gets the -connectionDidFinishLoading: message I remove the
    >> connection object from the set.  Works great now.
    >
    > Yep, that would work-around it.

    It's not a workaround... it looks as if Doug hadn't been using GC,
    he'd have been leaking an NSURLConnection.

    Hamish
  • On Feb 25, 2008, at 18:18, Doug Penny wrote:

    >> NSURLConnection *imageConnection = [[NSURLConnection alloc]
    >> initWithRequest:request
    >>
    >> delegate:self];
    >>
    >> if (!imageConnection) {
    >> NSLog(@"A problem was encountered while trying to download an
    >> image from %@", imageURL);
    >> }
    >>

    [sniped]

    > Turns out garbage collection was doing me in.  When the
    > NSURLConnection object was hanging out waiting for a response, it
    > would get collected.  To work around this, after creating the
    > NSURLConnection object I just stick it in a NSMutableSet.  When the
    > delegate gets the -connectionDidFinishLoading: message I remove the
    > connection object from the set.  Works great now.

    Any object you create on the stack will be gone when the method is
    finished :-)

    You must keep a reference to the connection.

    Best Regards,

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

    >> Turns out garbage collection was doing me in.  When the
    >> NSURLConnection object was hanging out waiting for a response, it
    >> would get collected.  To work around this, after creating the
    >> NSURLConnection object I just stick it in a NSMutableSet.  When the
    >> delegate gets the -connectionDidFinishLoading: message I remove the
    >> connection object from the set.  Works great now.
    >
    > Any object you create on the stack will be gone when the method is
    > finished :-)
    >
    > You must keep a reference to the connection.

    Or how about turning off garbage collection temporarily for the
    object? Something like:

    Create the connection and make sure it sticks around:

      theConnection = [[NSURLConnection alloc] initWithRequest:request
    delegate:self];
      [[NSGarbageCollector defaultCollector]
    disableCollectorForPointer:theConnection];

    Clean up when done:

    - (void)connection:(NSURLConnection *)connection didFailWithError:
    (NSError *)error
    {
    [...do your processing...]
    [[NSGarbageCollector defaultCollector]
    enableCollectorForPointer:connection];
    }

    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
    [...do your processing...]
    [[NSGarbageCollector defaultCollector]
    enableCollectorForPointer:connection];
    }

    This seems like less hassle to me, but I don't know if it is good
    form. Is it really better keep a strong reference to the connection
    object, and if so, why?

    António

    -----------------------------------------
    Perfume is the forgiveness
    that the trampled flower casts
    upon the heel that crushes it.
    -----------------------------------------