iPhone: How do I get the file path of an image saved with UIImageWriteToSavedPhotosAlbum()?

IphoneIosUiimageSavePhotolibrary

Iphone Problem Overview


I'm saving a merged image to the iPhone photo library using:

UIImageWriteToSavedPhotosAlbum(viewImage, self, @selector(savedPhotoImage:didFinishSavingWithError:contextInfo:), nil);

And getting the callback using:

- (void) savedPhotoImage:(UIImage*)image didFinishSavingWithError:(NSError *)error contextInfo: (void *)contextInfo { NSLog(@"%@", [error localizedDescription]);
NSLog(@"info: %@", contextInfo);}

What I would like to get is the path for where the image has been saved, so I can add it to an array which will be used to call up a list of saved items elsewhere in the app.

When I load the image using the picker it displays the path info. However when I save a created image, I can't find where to pull the saved image path.

I have search about the web, but most examples stop at the callback with a nice message to say the image was saved successfully. I would just like to be able to know where it was saved.

I understand one method might be to start defining my own paths, but as the method does that for me, I was just hoping it could tell me where it saved to.

Iphone Solutions


Solution 1 - Iphone

I finally found out the answer. Apparently the UIImage methods strip out metadata and so using UIImageWriteToSavedPhotosAlbum is no good.

However in ios4 Apple put in a new framework to handle the photo library called the ALAssetsLibrary.

First you need to right click on the Targets and in the build part, add the AlAsset Framework to your project with the little + icon in the bottom left.

Then add #import "AssetsLibrary/AssetsLibrary.h"; to the header file of your class.

Finally you can use the following code:

UIImage *viewImage = YOUR UIIMAGE  // --- mine was made from drawing context
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];  
// Request to save the image to camera roll  
[library writeImageToSavedPhotosAlbum:[viewImage CGImage] orientation:(ALAssetOrientation)[viewImage imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error){  
	if (error) {  
		NSLog(@"error");  
	} else {  
			NSLog(@"url %@", assetURL);  
	}  
}];  
[library release];

And that gets the path of the file you just saved.

Solution 2 - Iphone

My code is

-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
	UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
	
	imageURL = nil;
	
	ALAssetsLibraryWriteImageCompletionBlock completeBlock = ^(NSURL *assetURL, NSError *error){
		if (!error) {  
			#pragma mark get image url from camera capture.
			imageURL = [NSString stringWithFormat:@"%@",assetURL];
			
		}  
	};
	
	if(image){
		ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
		[library writeImageToSavedPhotosAlbum:[image CGImage] 
								  orientation:(ALAssetOrientation)[image imageOrientation] 
							  completionBlock:completeBlock];
	}
}

in .h import Library and define type def of ALAssetsLibraryWriteImageCompletionBlock

#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>

typedef void (^ALAssetsLibraryWriteImageCompletionBlock)(NSURL *assetURL, NSError *error);

if you don't know how to get <AssetsLibrary/AssetsLibrary.h>, please add existing framework (AssetsLibrary.framework)

Solution 3 - Iphone

OlivariesF's answer is missing the key part of this question, retrieve the path:

Here's a code snippet that does everything:

- (void)processImage:(UIImage*)image type:(NSString*)mimeType forCallbackId:(NSString*)callbackId
    {
        __block NSString* localId;
        
        // Add it to the photo library
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
            
            localId = [[assetChangeRequest placeholderForCreatedAsset] localIdentifier];
        } completionHandler:^(BOOL success, NSError *err) {
            if (!success) {
                NSLog(@"Error saving image: %@", [err localizedDescription]);
            } else {
                PHFetchResult* assetResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[localId] options:nil];
                PHAsset *asset = [assetResult firstObject];
                [[PHImageManager defaultManager] requestImageDataForAsset:asset
                                                                  options:nil
                                                            resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
                    NSURL *fileUrl = [info objectForKey:@"PHImageFileURLKey"];
                    if (fileUrl) {
                        NSLog(@"Image path: %@", [fileUrl relativePath]);
                    } else {
                        NSLog(@"Error retrieving image filePath, heres whats available: %@", info);
                    }
                }];
            }
        }];
    }

Solution 4 - Iphone

Swift Version will be

 ALAssetsLibrary().writeImageToSavedPhotosAlbum(editedImage.CGImage, orientation: ALAssetOrientation(rawValue: editedImage.imageOrientation.rawValue)!,
                completionBlock:{ (path:NSURL!, error:NSError!) -> Void in
                    print("\(path)")
            })

And "import ALAssetsLibrary" in your file.

Project-> Build Phases -> Link binary -> AssetsLibrary.framework

Solution 5 - Iphone

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
	
	RandomIndexnew = arc4random() % 3;
	if(RandomIndexnew == 0)
	{
	    nameStr =[NSString stringWithFormat:@"jpg"];
	    textFieldNormalFile_type.text =[NSString stringWithFormat:@"jpg"];
	}
	else if(RandomIndexnew = 1)
	{
		nameStr =[NSString stringWithFormat:@"gif"];
		textFieldNormalFile_type.text =[NSString stringWithFormat:@"GIF"];
	}
	else if(RandomIndexnew = 2)
	{
		nameStr =[NSString stringWithFormat:@"jpg"];
		textFieldNormalFile_type.text =[NSString stringWithFormat:@"JPG"];
	}
	
	RandomIndex = arc4random() % 20;
	NSString *nameStr1 =[NSString stringWithFormat:@"Image%i",RandomIndex];
	textFieldNormalFile_name.text =[NSString stringWithFormat:@"%@.%@",nameStr1,nameStr];
	
	newFilePath = [NSHomeDirectory() stringByAppendingPathComponent: textFieldNormalFile_name.text];
	imageData = UIImageJPEGRepresentation(img, 1.0);
	if (imageData != nil) {
		NSLog(@"HERE [%@]", newFilePath);
		[imageData writeToFile:newFilePath atomically:YES];
	}
	image.image =[UIImage imageNamed:newFilePath];
	NSLog(@"newFilePath:%@",newFilePath);
	path.text =[NSString stringWithFormat:newFilePath];
	NSLog(@"path.text :%@",path.text);
}

Solution 6 - Iphone

ALAssetsLibrary has been deprecated.

This is the way you should do it:

#import <Photos/Photos.h>

UIImage *yourImage;

[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
    [PHAssetChangeRequest creationRequestForAssetFromImage:yourImage];
} completionHandler:^(BOOL success, NSError *error) {
    if (success) {
        NSLog(@"Success");
    } else {
        NSLog(@"write error : %@",error);
    }
}];

Solution 7 - Iphone

Swift 4.1 version of OlivaresF's answer

        PHPhotoLibrary.shared().performChanges({
                PHAssetChangeRequest.creationRequestForAsset(from: image)
            }) { (success, error) in
                if success {
                    
                } else {
                }
            }

Solution 8 - Iphone

Swift version

            var localId = ""
            PHPhotoLibrary.shared().performChanges({
                let assetChangeRequest:PHAssetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: chosenImage)
                localId = assetChangeRequest.placeholderForCreatedAsset!.localIdentifier
            }) { (success, error) in
                let assetResult:PHFetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [localId], options: nil)
                let asset:PHAsset = assetResult.firstObject!
                PHImageManager.default().requestImageData(for: asset, options: nil) { (imageData, dataUTI, orientation, info) in
                    if let url:URL = info?["PHImageFileURLKey"] as? URL
                    {
                        print("\(url)")
                        
                    }
                    
                }
                
            }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBenView Question on Stackoverflow
Solution 1 - IphoneBenView Answer on Stackoverflow
Solution 2 - IphoneChalermchon SommanaView Answer on Stackoverflow
Solution 3 - IphonedriedlerView Answer on Stackoverflow
Solution 4 - IphoneAvijit NagareView Answer on Stackoverflow
Solution 5 - IphonesandyView Answer on Stackoverflow
Solution 6 - IphoneolivaresFView Answer on Stackoverflow
Solution 7 - IphonecvbView Answer on Stackoverflow
Solution 8 - IphoneVarun NahariaView Answer on Stackoverflow