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