dotKwame
dotKwame

Reputation: 181

Memory pressure due to download and saving of images

Fortunately I know where my memory pressure issue is coming from, and I have tried a number of techniques such as wrapping a block in an @autorelease block and setting objects to nil but still no success.

Sorry for dumping too much code here, I tried to cut it down to the essentials. Here is the code for downloading and saving images:

NSMuttableArray *photosDownOps = [NSMuttableArray array];
NSURL *URL = [...];
NSURLRequest *request = [...];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFImageResponseSerializer serializer];

[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {    
    dispatch_queue_t amBgSyncQueue = dispatch_queue_create("writetoFileThread", NULL);
    dispatch_async(amBgSyncQueue, ^{
        [self savePhotoToFile:(UIImage *)responseObject usingFileName:photo.id];
    });    
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    if ([error code] !=  NSURLErrorCancelled)
        NSLog(@"Error occured downloading photos: %@", error);
}];
[photosDownOps addObject:op];

NSArray *photosDownloadOperations = [AFURLConnectionOperation batchOfRequestOperations:photosDownloadOperatons 
                                                                         progressBlock:^(NSUInteger nof, NSUInteger tno) {        
} completionBlock:^(NSArray *operations) {
    NSLog(@"all photo downloads completed");
}];

[self.photosDownloadQueue addOperations:photosDownloadOperations waitUntilFinished:NO];

+ (void) savePhotoToFile:(UIImage *)imageToSave usingFileName:(NSNumber *)photoID{
    @autoreleasepool {
        NSData * binaryImageData = UIImageJPEGRepresentation(imageToSave, 0.6);
        NSString *filePath = [Utilities fullPathForPhoto:photoID];
        [binaryImageData writeToFile:filePath atomically:YES];
        binaryImageData = nil;
        imageToSave = nil;
    }
}

This situation though only happens with iPhone 4s devices that I have tested on, it does not happen on iPhone 5 models.

Upvotes: 1

Views: 580

Answers (2)

dotKwame
dotKwame

Reputation: 181

I managed to solve this by extending NSOperation and within the main block immediately after I receive the data I write it out to file:

- (void)main{
    @autoreleasepool {
        //...
        NSData *imageData = [[NSData alloc] initWithContentsOfURL:imageUrl];        
        if (imageData) {
            NSError *error = nil;
            [imageData writeToFile:imageSavePath options:NSDataWritingAtomic error:&error];
        }
        //...
    }
}

This NSOperation object was then added a NSOperationQueue I already had.

Upvotes: 1

Crazy Developer
Crazy Developer

Reputation: 3464

Try to create your own class to download image using NSUrlConnection and in the delegate method append that data to your file just see the below code

-(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data {

NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:aPath]; 
[fileHandle seekToEndOfFile]; 
[fileHandle writeData:data]; 
[fileHandle closeFile];

}

This will help you in memory management as all the data which is download is not need to cache .

Upvotes: 0

Related Questions