3

i have one NSMutableArray with some image url's. The images have sizes between 12KB to 6MB. I use AsycImageView class and implement but when large images are downloading application get crashed, I gave 6*1024*1024 (6MB) for maxsize in that class, increase time interval 60.0 sec to 180.o sec, but there is no use. I'm getting an error "Received memory warning" and when app crash automatically connection remove from device, but in simulator there is no crash.

Ravi
  • 888
  • 6
  • 24

5 Answers5

3

you can do this using multiThreading. Here is a code

- (UIImageView *)getImageFromURL:(NSDictionary *)dict
{
    #ifdef DEBUG
    NSLog(@"dict:%@", dict);
    #endif

    UIImageView *_cellImage = nil;
    _cellImage = ((UIImageView *)[dict objectForKey:@"image"]);
    NSString *strURL = [dict objectForKey:@"imageurl"]);

    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];

    #ifdef DEBUG
    NSLog(@"%i", data.length);
    #endif

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *dataFilePath = [NSString stringWithFormat:@"%@.png", [documentsDirectory stringByAppendingPathComponent:[dict objectForKey:@"imageid"]]];

    if (data) // i.e. file exist on the server
    {
        [data writeToFile:dataFilePath atomically:YES];
        _cellImage.image = [UIImage imageWithContentsOfFile:dataFilePath];
    }
    else // otherwise show a default image.
    {
        _cellImage.image = [UIImage imageNamed:@"nouser.jpg"];
    }
    return _cellImage;
}

And call this method in cellForRowAtIndexPath like this:

    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:imageURL, @"imageurl", self.imgPhoto, @"image", imageid, @"imageid", nil];
    [NSThread detachNewThreadSelector:@selector(getImageFromURL:) toTarget:self withObject:dict];

The code will start getting images in multiple threads and will save image locally to document folder. Also the image will not download again if already exists with the same name. Hope this helps

Vaibhav Saran
  • 12,848
  • 3
  • 65
  • 75
3

Use GCD for lazy loading.

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
 dispatch_async(queue, ^{
       NSString *strURL = url here;
       NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
       UIImage *image = nil;
       if(data)
        image = [UIImage imageWithData:data];
      dispatch_sync(dispatch_get_main_queue(), ^{
           //now use image in image View  or anywhere according to your requirement.
           if(image)
             yourImgView = image
      });
 });
Paresh Navadiya
  • 38,095
  • 11
  • 81
  • 132
  • when i use this code i got error "Expected expression" at UIImage *image=[UIImage imageWithData:data] @Prine – Ravi May 03 '13 at 07:25
1

You could download image asynchronously using GCD. Use the following code,

__block NSData *imageData;

dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, NULL);
dispatch_async(myQueue, ^{
  //load url image into NSData
  imageData = [NSData dataWithContentsOfURL: your_image_URL];
  if(imageData) {
    dispatch_sync(dispatch_get_main_queue(), ^{
        //convert data into image after completion
        UIImage *img = [UIImage imageWithData:imageData];
        //do what you want to do with your image
    });
 } else {
      NSLog(@"image not found at %@", your_image_URL);
 }
});
dispatch_release(myQueue);

For further info, see dispatch_queue_t

x4h1d
  • 6,042
  • 1
  • 31
  • 46
  • thank you x4h1d, where can i put this code, iam confuse AsycImageView class or my class – Ravi May 03 '13 at 06:57
  • @Raven, wherever you are gonna write NSData *imageData = [NSData dataWithContentsOfURL:your_image_URL]; UIImage *img = [UIImage imageWithData:imageData]; write the above code instead. – x4h1d May 03 '13 at 07:10
  • @Raven, if the answer works and you find it useful please accept and upvote it. Thank you. – x4h1d May 03 '13 at 08:06
0

I would recommend a drop in replacement API SDWebImage it provides a category for UIImageVIew with support for remote images coming from the web. you can also have a placeholder image till the images are downloaded Asynchronously . Its easy to use and saves a lot of work

Bonnie
  • 4,943
  • 30
  • 34
0

You're problem seems to be more of a memory usage issue than it is a performance issue.

If you really want to download image asynchronously I would recommend you use The UIImageView category from AFNetworking which has been fully tested and is very well maintained.

However here you run into memory warnings on your device (which obviously holds much less memory than your simulator which runs on your Mac).

So I would use first the static analyzer:

enter image description here

to see if leaks are present and then run a Leaks Instrument to track it down.

Hope this helps.

Community
  • 1
  • 1
apouche
  • 9,703
  • 6
  • 40
  • 45