I have created a class for fetching server-side data in my iOS-App, based on NSURLConnection, forwarding the fetched data to a delegate for processing.
When downloading text/json this works perfectly.
I am now expanding to fetch some png-images and can’t get the data through.
I have located that it breaks in the didReceiveData-call, where [receivedData appendData:data] do not do anything for the received image-data.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Append the new data to receivedData.
[receivedData appendData:data];
}
I get data into this method (NSData >0 bytes), but calling [receivedData appendData:data] do not change the size of receivedData (Still 0 bytes).
As this works perfectly with text and not with image-data I believe it has something to do with characterset or encoding to do, but cannot find anything on this.
Any help is appreciated.
Update with requested code-samples:
In the method that makes the call:
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData to hold the received data.
receivedData = [NSMutableData data];
// Also tried with no change in behaviour
// receivedData = [[NSMutableData alloc] initWithLength:0];
} else {
// Inform the user that the connection failed.
}
My didReceiveResponse:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
Another UPDATE
Turns out the problem bois down to concurrency as I fire three instances of the class simultaniously to fetch three files asynchroniously. The problem is that the first releases receivedData when finishing ruining the response from the two other instances.
How do I make sure that each instance of the class has their own receivedData to play with?
Final Notes
Using a dictionary of MutableArrays for the retreived data solves the concurrency-problem.
It also seems like defining the MutableArray as a private property of the class creates one array for each instance.
@interface MyClass(){
@private NSMutableData * receivedData;
}
Do you ever initialize
receivedData?Something like this would do it:
An even faster approach is to initialize it right before you kick off the actual request (so that it’s not being checked every time data is received).
also remember to nil
receivedDatawhen your request is completed and you are done extracting it so that it will be ready to go for the next request.Here’s one solution for concurrent requests:
Instead of a single NSMutableData property, create an NSMutableDictionary so that you can hang on to multiple instances at once.
NSMutableDictionary *receivedDataNow, once you put together your NSURLConnection (let’s call it
urlConnection), you can create a new unique data object and put it in your dictionary. You should be able to use the string description of the connection as your unique key.Now you can do this:
Once your connection has completed, remember to call
removeObjectForKeyto get rid of data objects once they are no longer needed.