简体   繁体   中英

UITableView scrolling not smooth due to processing

I'm using a UITableView to show 2 to 3 images as thumbnail in each table view cell. The images which I'm showing it in the tableview are huge in size. If I'm using those images directly without any size reduction then the tableview may lose some images if I move back and forth between TableView and other view controllers.

So, I thought of size reduction code which reduces the size of the images. The code given below works great and the previous issue was fixed. But the tableview looses its smooth scrolling because the size reduction code uses a lot of memory. Every time when a new tableview cell is shown, it processes (reduces the size) the images in the particular tableview cell.

There may be a simple solution for this. Thanks in Advance.

//Size Reduction Code

CGSize newSize=CGSizeMake(_new_width, _new_height);
UIGraphicsBeginImageContext( newSize );
[sd._image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
scene_image_preview.image =newImage;

On top of reducing the image you can store the resulting newImage as a file in the documents folder of your app.

  NSData *imageData = UIImagePNGRepresentation([UIImage imageWithCGImage:newImage]);
  CGImageRelease(newImage);
  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  NSString *documentsDirectory = [paths objectAtIndex:0];
  NSString *path = [NSString stringWithFormat:@"%@/%@%d_%d.png",documentsDirectory, prefix, x, y];
  [imageData writeToFile:path atomically:NO];

Depending on how many images you have, you can just keep all the reduced-size images in an NSMutableDictionary that's a property of your class.

In other words:

In your header

@property (nonatomic, retain) NSMutableDictionary *sizedImages;

Then in your cellForRowAtIndexPath: code

UIImage *sizedImage = [sizedImages objectForKey:[NSNumber numberWithInt:indexPath.row]];  
//Or you could use the filename as the key

if (!sizedImage) {  
        sizedImage = [self sizeImage];(your sizing method)
        [sizedImages setObject:sizedImage forKey:[NSNumber numberWithInt:indexPath.row]];  
}

A few possible options

  • Perform the resizing in the background so it doesn't hold up the main thread.
  • Cache the resized image after doing it so there is only a delay the first time (this could be used in conjunction with doing it in the background so there is no delay on the scrolling)
  • Are you downloading the images? If so, download a thumbnail first and display that. Then if the image is selected, display the thumbnail scaled up to full screen which will look blocky, but then download the full-size image in the background and display that when it has loaded.
  • If you aren't downloading the images, but they are included in the app, just include thumbnails as well and display them instead

drawing images usually takes time.i think you can try to place the images in imageView by giving the frame sizes as desired.i doesn't make difference in look of the images.

add the imageviews to the cell and add the images to the imageView

These two links are very useful

http://www.fieryrobot.com/blog/2008/10/01/glassy-scrolling-with-uitableview/

and his follow up post

http://www.fieryrobot.com/blog/2008/10/08/more-glassy-scrolling-with-uitableview/

The first link is a few best practices. The second link will eb more useful to you; render your whole table view cell to an image and use that instead - this can be cached to disk to free memory & can be used between runs of the app.

- (void)saveImage:(UIImage *)image withName:(NSString *)name {

            [myArray addObject:name];

        //save image
            NSData *data = UIImageJPEGRepresentation(image, 1.0);
            NSFileManager *fileManager = [NSFileManager defaultManager];
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
            NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
            [fileManager createFileAtPath:fullPath contents:data attributes:nil];

    }

    - (UIImage *)loadImage:(NSString *)name {

        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
            NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];    
            UIImage *res = [UIImage imageWithContentsOfFile:fullPath];

            return res;
    }

Finally, I got a solution to load number of large sized images simultaneously. First, I reduced the size of the image using the size reduction code above and I saved those sized images to documents directory for the first time and then I loaded the saved images from the documents directory using these saveImage and loadImage functions.

Thanks for all the comments and suggestions to solve this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM