Images taken from camera roll take long time to di

2019-07-31 08:13发布

问题:

I am using this class to take images from a UIImagePickerController/Camera, store them in the documents directory and display them to the user. Essentially this codes works, however it takes a very long time to actually display the data in the UITableView after the user selects an image (10+ seconds at least).

Here is my class (not the full class, just the problem code):

#import "ReceiptImageViewController.h"
#import "ReceiptImageCell.h"

@interface ReceiptImageViewController ()

@end

@implementation ReceiptImageViewController

@synthesize fields;
@synthesize receiptNumber;
@synthesize delegate;

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    images = [[NSMutableArray alloc] init];

    //Set UI Colors
    self.navigationController.navigationBar.tintColor = [UIColor blackColor];
    self.navigationController.toolbar.tintColor = [UIColor blackColor];
}

- (void) viewDidAppear:(BOOL)animated{
    NSLog(@"ViewDidAppear");
    [self.tableView reloadData];
    NSLog(@"Table Data Reloaded");
}

- (void)viewDidUnload
{
    [super viewDidUnload];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    [images removeAllObjects];
    for (NSString *path in fields)
    {
        if (![path isEqualToString:@""])
        {
            UIImage *image = [UIImage imageWithContentsOfFile:path];
            [images addObject:image];
            NSLog(@"Adding Image");
        }
        NSLog(@"Loop");
    }
    return [images count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"ReceiptImageCell";
    ReceiptImageCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Configure the cell...
    //Set info label text
    cell.infoLabel.text = [NSString stringWithFormat:@"Receipt Image: %d", indexPath.row];
    cell.receiptImage.image = [images objectAtIndex:indexPath.row];

    return cell;
}

#pragma mark - UIActionSheet Delegate

//Displays action sheet when the user presses
//'+' button next to image view
-(IBAction)showActionSheet:(id)sender{

    UIActionSheet *popupQuery = [[UIActionSheet alloc] initWithTitle:@"Receipt Image" 
                                                            delegate:self 
                                                   cancelButtonTitle:@"Cancel"
                                              destructiveButtonTitle:NULL 
                                                   otherButtonTitles:@"Take Picture", @"Choose From Library", nil];
    popupQuery.actionSheetStyle = UIActionSheetStyleBlackOpaque;
    popupQuery.tag = 0;
    [popupQuery showInView:self.view];

    //    //FOR TESTING ON SIMULATOR 
//    UIImage* image = [UIImage imageNamed:@"Receipt1.jpg"];
//    int i = [self.tableView numberOfRowsInSection:0] + 1;
//    NSString* imageName = [NSString stringWithFormat:@"Receipt%@Image%d", receiptNumber, i];
//    [self saveImage:image :imageName];
}

//Saves receipt image to documents directory
- (void)saveImage:(UIImage*)image:(NSString*)imageName 
{ 
    NSData *imageData = UIImagePNGRepresentation(image); //convert image into .png format.

    NSFileManager *fileManager = [NSFileManager defaultManager];//create instance of NSFileManager

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //create an array and store result of our search for the documents directory in it

    NSString *documentsDirectory = [paths objectAtIndex:0]; //create NSString object, that holds our exact path to the documents directory

    NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", imageName]]; //add our image to the path 

    [fileManager createFileAtPath:fullPath contents:imageData attributes:nil]; //finally save the path (image)

    [fields addObject:fullPath];

    [self.tableView reloadData];

    NSLog(@"image saved");
}

#pragma mark - UIImagePickerControllerDelegate

//Receive the image the user picks from the image picker controller
-(void)imagePickerController:(UIImagePickerController*)picker
didFinishPickingMediaWithInfo:(NSDictionary*)info {
    // Do stuff to image.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        UIImage* image = [info objectForKey: UIImagePickerControllerOriginalImage];
        int i = [self.tableView numberOfRowsInSection:0] + 1;
        NSString* imageName = [NSString stringWithFormat:@"Receipt%@Image%d", receiptNumber, i];
        [self saveImage:image :imageName];
    });

    [self dismissModalViewControllerAnimated:YES];
}

-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (actionSheet.tag == 0){
        if (buttonIndex == 0) {
            NSLog(@"Take Picture Button Clicked");
            // Create image picker controller
            UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];

            // Set source to the camera
            imagePicker.sourceType =  UIImagePickerControllerSourceTypeCamera;

            // Delegate is self
            imagePicker.delegate = self;

            // Show image picker
            [self presentModalViewController:imagePicker animated:YES];
        } 
        else if (buttonIndex == 1) {
            NSLog(@"Choose From Library Button Clicked");
            // Create image picker controller
            UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];

            // Set source to the camera
            imagePicker.sourceType =  UIImagePickerControllerSourceTypePhotoLibrary;

            // Delegate is self
            imagePicker.delegate = self;

            // Show image picker
            [self presentModalViewController:imagePicker animated:YES];
        } 
        else if (buttonIndex == 2) {
            NSLog(@"Cancel Button Clicked");
        } 
    }
}

Can anyone explain why this happens? I've run into this problem in other applications and have never managed to find a solution..Even one that involves using activity indicators or similar?

Thanks a lot,

Jack