iOS save photo in an app specific album
I'm creating an iOS 5 app. I want to save a photo to the device.
I want to save the photo to an album specific to my app, so I need to create the album, and then save photos to the album.
I know how to create the album:
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library addAssetsGroupAlbumWithName:@"MY APP NAME" resultBlock:^(ALAssetsGroup *group) {
//How to get the album URL?
} failureBlock:^(NSError *error) {
//Handle the error
}];
I want add photos to the new album now, how do I do so? Sample code is greatly appreciated!
Solution 1:
You may use the following code just change the name of album :
__weak ALAssetsLibrary *lib = self.library;
[self.library addAssetsGroupAlbumWithName:@"My Photo Album" resultBlock:^(ALAssetsGroup *group) {
///checks if group previously created
if(group == nil){
//enumerate albums
[lib enumerateGroupsWithTypes:ALAssetsGroupAlbum
usingBlock:^(ALAssetsGroup *g, BOOL *stop)
{
//if the album is equal to our album
if ([[g valueForProperty:ALAssetsGroupPropertyName] isEqualToString:@"My Photo Album"]) {
//save image
[lib writeImageDataToSavedPhotosAlbum:UIImagePNGRepresentation(image) metadata:nil
completionBlock:^(NSURL *assetURL, NSError *error) {
//then get the image asseturl
[lib assetForURL:assetURL
resultBlock:^(ALAsset *asset) {
//put it into our album
[g addAsset:asset];
} failureBlock:^(NSError *error) {
}];
}];
}
}failureBlock:^(NSError *error){
}];
}else{
// save image directly to library
[lib writeImageDataToSavedPhotosAlbum:UIImagePNGRepresentation(image) metadata:nil
completionBlock:^(NSURL *assetURL, NSError *error) {
[lib assetForURL:assetURL
resultBlock:^(ALAsset *asset) {
[group addAsset:asset];
} failureBlock:^(NSError *error) {
}];
}];
}
} failureBlock:^(NSError *error) {
}];
Solution 2:
For anyone looking to do this as of iOS 9, things have gotten a bit more complicated since the ALAssetsLibrary is deprecated in favor of the new Photos library.
Here's some Swift code for adding UIImages to a specific album name (creating the album if it doesn't exist), you may need to do some refactoring/optimization for your needs:
func insertImage(image : UIImage, intoAlbumNamed albumName : String) {
//Fetch a collection in the photos library that has the title "albumNmame"
let collection = fetchAssetCollectionWithAlbumName(albumName)
if collection == nil {
//If we were unable to find a collection named "albumName" we'll create it before inserting the image
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
PHAssetCollectionChangeRequest.creationRequestForAssetCollectionWithTitle(albumName)
}, completionHandler: {(success : Bool, error : NSError?) in
if error != nil {
print("Error: " + error!.description)
}
if success {
//Fetch the newly created collection (which we *assume* exists here)
let newCollection = self.fetchAssetCollectionWithAlbumName(albumName)
self.insertImage(image, intoAssetCollection: newCollection!)
}
}
)
} else {
//If we found the existing AssetCollection with the title "albumName", insert into it
self.insertImage(image, intoAssetCollection: collection!)
}
}
func fetchAssetCollectionWithAlbumName(albumName : String) -> PHAssetCollection? {
//Provide the predicate to match the title of the album.
let fetchOption = PHFetchOptions()
fetchOption.predicate = NSPredicate(format: "title == '" + albumName + "'")
//Fetch the album using the fetch option
let fetchResult = PHAssetCollection.fetchAssetCollectionsWithType(
PHAssetCollectionType.Album,
subtype: PHAssetCollectionSubtype.AlbumRegular,
options: fetchOption)
//Assuming the album exists and no album shares it's name, it should be the only result fetched
let collection = fetchResult.firstObject as? PHAssetCollection
return collection
}
func insertImage(image : UIImage, intoAssetCollection collection : PHAssetCollection) {
//Changes for the Photos Library must be maded within the performChanges block
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
//This will request a PHAsset be created for the UIImage
let creationRequest = PHAssetCreationRequest.creationRequestForAssetFromImage(image)
//Create a change request to insert the new PHAsset in the collection
let request = PHAssetCollectionChangeRequest(forAssetCollection: collection)
//Add the PHAsset placeholder into the creation request.
//The placeholder is used because the actual PHAsset hasn't been created yet
if request != nil && creationRequest.placeholderForCreatedAsset != nil {
request!.addAssets([creationRequest.placeholderForCreatedAsset!])
}
},
completionHandler: { (success : Bool, error : NSError?) in
if error != nil {
print("Error: " + error!.description)
}
}
)
}