Search code examples
iosobjective-cuiimageviewuiimagepickercontroller

Can't Revert Back to Original Image After Using UIImagePickerController


I am having an interesting little problem using the uiimagepickercontroller and was wondering if anyone has any insight as to what might be happening. Users can take pictures with the camera or pick from the photo library until the cows come home as many times in a row as they like. My issue lies in allowing users to revert back to the original image that shipped with the app. Here is the flow:

  1. Users go the the tableview which shows a thumbnail of the image.
  2. Users navigate to the detail view which shows a larger view of the image.
  3. Users can tap on the image in the detail view to bring up a custom alertcontroller with options to a) use the camera to take a picture, b) use a picture from their library, or c) revert back to the original image.
  4. Users choose either option 'a' or option 'b' to either take a picture or use a picture from the photo library. IF they IMMEDIATELY change their mind about using one of those choices and want to just go back to using the original image, nothing happens! They can snap another picture or choose another image right away, but cannot revert back to the original image right away.

Reverting back to the original image DOES work perfectly when the app has been closed and then opened again. Sometimes it will work if you navigate around to other views within the app and then come back to the detail view where they just added their own image. By why the delay? I've searched around for two weeks but have not found anything resembling my problem or any solutions that help in any way (like reloading the headerview where image is sitting). Any thoughts?

Also I have figured out how to save the image to iCloud by using the documentation but cannot figure out how to retrieve them so there is no code for that. That is entirely different question. The same thing seems to occur even without that code.

Thanks for taking the time to look at this!

Here is some code:

    -(void)bookImageTapped:(UIGestureRecognizer *)gesture
{
    URBAlertView *changeImageAlertView = [[URBAlertView alloc] initWithTitle:@"Add A New Book Cover Image" message:nil cancelButtonTitle:@"Cancel" otherButtonTitles:@"Use Camera", @"Open Gallery", @"Use Original Photo", nil];
    [changeImageAlertView setHandlerBlock:^(NSInteger buttonIndex, URBAlertView *alertView) {

        [self checkPermission];

        if (PHAuthorizationStatusAuthorized)
        {
            if(buttonIndex == 0)
            {
                if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
                {
                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                        UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
                        pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
                        pickerController.delegate = self;
                        pickerController.allowsEditing = NO;
                        pickerController.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
                        [self presentViewController:pickerController animated:YES completion:nil];
                    }];

                    [alertView hide];
                }
                else
                {
                    NSLog(@"Camera not available");
                    [alertView hide];
                }
            }
            else if (buttonIndex == 1)
            {
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
                    pickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
                    pickerController.delegate = self;
                    pickerController.allowsEditing = NO;
                    pickerController.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
                    [self presentViewController:pickerController animated:YES completion:nil];
                }];
                [alertView hide];
            }
            else if (buttonIndex == 2)
            {
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    [self restoreOriginalPhoto];
                }];
                [alertView hide];
            }
            else
            {
                NSLog(@"button 2 cancel");
                [alertView hide];
            }
        }

        }];

        [changeImageAlertView show];

}

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(nonnull NSDictionary<NSString *,id> *)info
{
    [picker dismissViewControllerAnimated:YES completion:nil];
    _book.largeBookImage = [info objectForKey:UIImagePickerControllerOriginalImage];
    _book.largeBookImage = [self scaleImage:_book.largeBookImage toSize:CGSizeMake(120, 168)];
    _bookImageView.image = _book.largeBookImage;

    _book.wasNewImageAdded = YES;
    _book.originalImageUsed = NO;

    NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    [self saveImage:_book.largeBookImage withFileName:_book.bookImageID ofType:@"jpg" inDirectory:documentsDirectory];

}

-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [picker dismissViewControllerAnimated:YES completion:nil];
}

-(void)saveImage:(UIImage *)image withFileName:(NSString *)imageName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath
{
    if ([[extension lowercaseString] isEqualToString:@"png"])
    {
        [UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"png"]] options:NSAtomicWrite error:nil];

        //Create a URL to the local file
        NSURL *resourceURL = [NSURL fileURLWithPath:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"png"]]];
        if (resourceURL)
        {
            CKAsset *asset = [[CKAsset alloc] initWithFileURL:resourceURL];
            //create a record object
            CKRecord *bookCover = [[CKRecord alloc] initWithRecordType:@"Bookcover"];
            //set the record's fields
            bookCover[@"title"] = _book.title;
            bookCover[@"bookImage"] = asset;

            /* TO SAVE A RECORD */
            //get the public database
            CKContainer *appContainer = [CKContainer defaultContainer];
            CKDatabase *publicDatabase = [appContainer publicCloudDatabase];
            [publicDatabase saveRecord:bookCover completionHandler:^(CKRecord *bookCover, NSError *error) {
                if (error)
                {
                    //insert error handling
                    return;
                }
                //insert succesfully saved record code
                NSLog(@"png record saved after using picker!");
            }];
        }
    }
    else if ([[extension lowercaseString] isEqualToString:@"jpg"] || [[extension lowercaseString] isEqualToString:@"jpeg"])
    {
        [UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"jpg"]] options:NSAtomicWrite error:nil];

        //Create a URL to the local file
        NSURL *resourceURL = [NSURL fileURLWithPath:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"jpg"]]];
        if (resourceURL)
        {
            CKAsset *asset = [[CKAsset alloc] initWithFileURL:resourceURL];
            //create a record object
            CKRecord *bookCover = [[CKRecord alloc] initWithRecordType:@"Bookcover"];
            //set the record's fields
            bookCover[@"title"] = _book.title;
            bookCover[@"bookImage"] = asset;

            /* TO SAVE A RECORD */
            //get the public database
            CKContainer *appContainer = [CKContainer defaultContainer];
            CKDatabase *publicDatabase = [appContainer publicCloudDatabase];
            [publicDatabase saveRecord:bookCover completionHandler:^(CKRecord *bookCover, NSError *error) {
                if (error)
                {
                    //insert error handling
                    return;
                }
                //insert succesfully saved record code
                NSLog(@"jpg record saved after using picker!");
            }];
        }
    }
    else
    {
        NSLog(@"Image Save Failed\nExtension: (%@) is not recognized, use (PNG/JPG)", extension);
    }
}

- (UIImage *) scaleImage:(UIImage*)image toSize:(CGSize)newSize 
{
    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

-(void)restoreOriginalPhoto
{
    NSLog(@"restore photo called");

    _book.originalImageUsed = YES;
    _book.wasNewImageAdded = NO;

    _bookImageView.image = _book.largeBookImage;

    NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    [self saveImage:_book.largeBookImage withFileName:_book.bookImageID ofType:@"jpg" inDirectory:documentsDirectory];


}

Here is the headerview with the imageview:

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    _headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 26)];
    _headerView.backgroundColor = [UIColor colorWithRed:8/255.0 green:46/255.0 blue:46/255.0 alpha:0.8];

if (section == 0)
{
    _headerView.backgroundColor = [UIColor whiteColor];

    _bookImageView = [[UIImageView alloc] initWithFrame:CGRectMake((tableView.frame.size.width - 120)/2, 6, 120, 168)];
    _bookImageView.contentMode = UIViewContentModeScaleAspectFit;


    if (_book.wasNewImageAdded)
    {
        NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        UIImage * image = [self loadImageWithFileName:_book.bookImageID ofType:@"jpg" inDirectory:documentsDirectory];
        _bookImageView.image = image;

    }
    else
    {
        _bookImageView.image = _book.largeBookImage;
    }

    if(_book.originalImageUsed)
    {
        NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        UIImage * image = [self loadImageWithFileName:_book.bookImageID ofType:@"jpg" inDirectory:documentsDirectory];
        _bookImageView.image = image;
    }

    UITapGestureRecognizer *bookImageTouched = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(bookImageTapped:)];
    bookImageTouched.numberOfTapsRequired = 1;
    [_bookImageView addGestureRecognizer:bookImageTouched];
    _bookImageView.userInteractionEnabled = YES;

    [_headerView addSubview:_bookImageView];
}

Solution

  • I finally figured it out! It seems that I was confusing xcode with my property names. The code ended up much simpler in the end.

    In didFinishPickingMediaWithInfo I created a UIImage and then set it to the bookImageView.image. Later, when I wanted to be able to update the image back to the original image, then I could call the bundle asset, _book.largeBookImage. Voila! The image was able to update immediately.

    The most pertinent code is posted below.

    -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(nonnull NSDictionary<NSString *,id> *)info
    {
        [picker dismissViewControllerAnimated:YES completion:nil];
    
        _chosenImage = [[UIImage alloc] init];
        _chosenImage = [info objectForKey:UIImagePickerControllerOriginalImage];
    
        _bookImageView.image = _chosenImage;
    
        _book.wasNewImageAdded = YES;
        _book.originalImageUsed = NO;
    
        NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        [self saveImage:_chosenImage withFileName:_book.bookImageID ofType:@"jpg" inDirectory:documentsDirectory];
    }
    
    -(void)saveImage:(UIImage *)image withFileName:(NSString *)imageName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath
    {
        if ([[extension lowercaseString] isEqualToString:@"png"])
        {
            [UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"png"]] options:NSAtomicWrite error:nil];
    
            [self.tableView reloadData];
        }
        else if ([[extension lowercaseString] isEqualToString:@"jpg"] || [[extension lowercaseString] isEqualToString:@"jpeg"])
        {
            [UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"jpg"]] options:NSAtomicWrite error:nil];
    
            [self.tableView reloadData];
        }
        else
        {
            //NSLog(@"Image Save Failed\nExtension: (%@) is not recognized, use (PNG/JPG)", extension);
        }
    }
    
    -(void)restoreOriginalPhoto
    {   
        _book.originalImageUsed = YES;
        _book.wasNewImageAdded = NO;
    
        _bookImageView.image = _book.largeBookImage;
        _backgroundImage.image = _book.largeBookImage; 
    }
    
    -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
    {   
        if (section == 0)
        {
          _bookImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 120, 168)];
            _bookImageView.contentMode = UIViewContentModeScaleAspectFit;
            _bookImageView.clipsToBounds = YES;
            _bookImageView.layer.cornerRadius = 10.0f;
    
            if (_book.wasNewImageAdded)
            {
                NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
                UIImage * image = [self loadImageWithFileName:_book.bookImageID ofType:@"jpg" inDirectory:documentsDirectory];
                _bookImageView.image = image;
            }
            else
            {
                _bookImageView.image = _book.largeBookImage;
            }
    
            if(_book.originalImageUsed)
            {
                _bookImageView.image = _book.largeBookImage;
            }
        }
    }
    
    -(void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
    
        if(_book.originalImageUsed)
        {
            _bookImageView.image = _book.largeBookImage;
        }
    
        [self.tableView reloadData];
        [self.tableView setContentOffset:CGPointZero animated:NO];
    }