iOS 4.0.1 SDK, Simulator 4.0. The behavior matches a bug report on 3.x device.

I have a problem with NSURLConnection that I've solved, but I don't trust the 
solution, so I'd like some assurance that I'm doing the right thing.

As you see in the code excerpt, I start a download asynchronously, with self as 
the delegate. I allocate an NSMutableData object to accumulate the downloaded 
data. Data goes into the accumulator in the connection:didReceiveData: callback.

The didReceiveData: callback asserts that the data accumulator exists. In 
certain circumstances (it seems to be with four of these requests started 
nearly simultaneously), the assertion is triggered. self.dataAccumulator is 
nil, and there is a significant amount of data coming in - 30K out of a 200K 
image.

One of the places I nil-out dataAccumulator is in the 
connectionDidFinishLoading: callback. I find that if I cancel the connection in 
the didFinishLoading/didFailWithError callbacks, the bug goes away. And, 
despite apparently missing incoming data (which seemed to have been arriving 
after the download had completed or failed), the data that did accumulate is 
correct and complete.

So okay, the error is silenced. But I'm not happy. I don't understand why 
additional, and apparently duplicative, data should be coming in after the 
completion callback. Isn't the download supposed to be... complete? Why should 
I have to cancel a connection on which NSURLConnection says there should be no 
more traffic?

   — F

@property(nonatomic, copy) NSURL *              url;
@property(nonatomic, retain) NSURLConnection *  downloadConnection;
@property(nonatomic, retain) NSMutableData *    dataAccumulator;


- (void) loadAsync
{
   self.dataAccumulator = [NSMutableData data];

   //  The URL scheme is http:.
   NSURLRequest *  req = [NSURLRequest requestWithURL: self.url];
   self.downloadConnection = [NSURLConnection connectionWithRequest: req
                                                           delegate: self];
   [self.downloadConnection start];
}

#pragma mark -
#pragma mark NSURLConnectionDelegate

- (void) connection: (NSURLConnection *) connection
    didReceiveData: (NSData *) data
{
   //  I'd better have a place to put the data:
   NSAssert1(self.dataAccumulator,
             @"%s: No data accumulator",
             __PRETTY_FUNCTION__);
   //  In the bug, this assertion fires.

   //  Accumulate the incoming data.
   [self.dataAccumulator appendData: data];
}

- (void) connectionDidFinishLoading: (NSURLConnection *) connection
{
   //////////////////////////////////////
   [self.downloadConnection cancel];   //  This shouldn't be necessary.
   //////////////////////////////////////

   //  ... do something with the contents of self.dataAccumulator.
   //  This would include creating a UIImage and writing the data
   //  to a cache file. Then...

   //  Get rid of the temporary data.
   self.dataAccumulator = nil;

   //  Clean up the download connection.
   //  Don't absolutely release it in one of its callbacks...
   [[self.downloadConnection retain] autorelease];

   //  ... but do release my hold on it.
   self.downloadConnection = nil;

   //  Believe me, I'd like to nil-out the NSURLConnection's
   //  delegate reference, but that's not in the class's API.
}
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to