I am developing an iPhone photo application, so i need to create a separate album with a name "My Album" in camera roll and i need to save my UIImageView image with custom name for example "My Image.png" inside the newly created directory.
How can i do this?
You can create a custom album and add an image pretty easy with these lines of code in iOS:
// Create the new album.
__block PHObjectPlaceholder *myAlbum;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCollectionChangeRequest *changeRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
myAlbum = changeRequest.placeholderForCreatedAssetCollection;
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[myAlbum.localIdentifier] options:nil];
PHAssetCollection *assetCollection = fetchResult.firstObject;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
// add asset
PHAssetCollectionChangeRequest *assetCollectionChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
[assetCollectionChangeRequest addAssets:@[[assetChangeRequest placeholderForCreatedAsset]]];
} completionHandler:^(BOOL success, NSError *error) {
if (!success) {
NSLog(@"Error: %@", error);
}
}];
} else {
NSLog(@"Error: %@", error);
}
}];
Since the AssetsLibrary
is deprecated, please use the Photos
framework instead (iOS 8 and later).
// Deprecated!
import AssetsLibrary
// Swift 3.0
let assetsLibrary = ALAssetsLibrary()
assetsLibrary.addAssetsGroupAlbum(withName: "NewAlbum", resultBlock: { assetsGroup in
print(assetsGroup == nil ? "Already created" : "Success")
}, failureBlock: { error in
print(error)
})
You can use the shared PHPhotoLibrary
object to create new photos but you can't give them specific names because you will be working with assets that need to be managed by the Photos.app. Each asset has specific properties. You can fetch objects, request changes, asset/thumbnail loading and caching, etc.
To create a custom album, please use the PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle:
).
Brief example:
// Swift 3.0
func createPhotoLibraryAlbum(name: String) {
var albumPlaceholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
// Request creating an album with parameter name
let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: name)
// Get a placeholder for the new album
albumPlaceholder = createAlbumRequest.placeholderForCreatedAssetCollection
}, completionHandler: { success, error in
if success {
guard let placeholder = albumPlaceholder else {
fatalError("Album placeholder is nil")
}
let fetchResult = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
guard let album: PHAssetCollection = fetchResult.firstObject else {
// FetchResult has no PHAssetCollection
return
}
// Saved successfully!
print(album.assetCollectionType)
}
else if let e = error {
// Save album failed with error
}
else {
// Save album failed with no error
}
})
}
Don't forget to import Photos
library.
To create a new photo asset on that album, please use the PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle:
).
// Swift 3.0
func createPhotoOnAlbum(photo: UIImage, album: PHAssetCollection) {
PHPhotoLibrary.shared().performChanges({
// Request creating an asset from the image
let createAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: photo)
// Request editing the album
guard let albumChangeRequest = PHAssetCollectionChangeRequest(for: album) else {
// Album change request has failed
return
}
// Get a placeholder for the new asset and add it to the album editing request
guard let photoPlaceholder = createAssetRequest.placeholderForCreatedAsset else {
// Photo Placeholder is nil
return
}
albumChangeRequest.addAssets([photoPlaceholder] as NSArray)
}, completionHandler: { success, error in
if success {
// Saved successfully!
}
else if let e = error {
// Save photo failed with error
}
else {
// Save photo failed with no error
}
})
}
UPDATE:
We need to request access to be able to use the Photos library:
PHPhotoLibrary.requestAuthorization { status in
switch status {
...
}
As of iOS 10 and above we also need to add entry for access in the target .plist file for "Privacy - Photo Library Usage Description":
<key>NSPhotoLibraryUsageDescription</key>
<string>Access to photos is needed to provide app features</string>
It was working from since iOS 5.0.
Please import AssetsLibrary/AssetsLibrary.h
ALAssetsLibrary* libraryFolder = [[ALAssetsLibrary alloc] init];
[libraryFolder addAssetsGroupAlbumWithName:@"My Album" resultBlock:^(ALAssetsGroup *group)
{
NSLog(@"Adding Folder:'My Album', success: %s", group.editable ? "Success" : "Already created: Not Success");
} failureBlock:^(NSError *error)
{
NSLog(@"Error: Adding on Folder");
}];
Create a new album:
func createAlbum(withTitle title: String, completionHandler: @escaping (PHAssetCollection?) -> ()) {
DispatchQueue.global(qos: .background).async {
var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: title)
placeholder = createAlbumRequest.placeholderForCreatedAssetCollection
}, completionHandler: { (created, error) in
var album: PHAssetCollection?
if created {
let collectionFetchResult = placeholder.map { PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [$0.localIdentifier], options: nil) }
album = collectionFetchResult?.firstObject
}
completionHandler(album)
})
}
}
Get an album with with a specified name:
func getAlbum(title: String, completionHandler: @escaping (PHAssetCollection?) -> ()) {
DispatchQueue.global(qos: .background).async { [weak self] in
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", title)
let collections = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let album = collections.firstObject {
completionHandler(album)
} else {
self?.createAlbum(withTitle: title, completionHandler: { (album) in
completionHandler(album)
})
}
}
}
And save a photo to a Photos album:
func save(photo: UIImage, toAlbum titled: String completionHandler: @escaping (Bool, Error?) -> ()) {
getAlbum(title: titled) { (album) in
DispatchQueue.global(qos: .background).async {
PHPhotoLibrary.shared().performChanges({
let assetRequest = PHAssetChangeRequest.creationRequestForAsset(from: photo)
let assets = assetRequest.placeholderForCreatedAsset
.map { [$0] as NSArray } ?? NSArray()
let albumChangeRequest = album.flatMap { PHAssetCollectionChangeRequest(for: $0) }
albumChangeRequest?.addAssets(assets)
}, completionHandler: { (success, error) in
completionHandler(success, error)
})
}
}
}
You can try My below Method for Create Album for iOS 7 and iOS 8
#define PHOTO_ALBUM_NAME @"AlbumName Videos"
-(void)createAlbum{
// PHPhotoLibrary_class will only be non-nil on iOS 8.x.x
Class PHPhotoLibrary_class = NSClassFromString(@"PHPhotoLibrary");
if (PHPhotoLibrary_class) {
// iOS 8..x. . code that has to be called dynamically at runtime and will not link on iOS 7.x.x ...
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:PHOTO_ALBUM_NAME];
} completionHandler:^(BOOL success, NSError *error) {
if (!success) {
NSLog(@"Error creating album: %@", error);
}else{
NSLog(@"Created");
}
}];
}else{
[self.library addAssetsGroupAlbumWithName:PHOTO_ALBUM_NAME resultBlock:^(ALAssetsGroup *group) {
NSLog(@"adding album:'Compressed Videos', success: %s", group.editable ? "YES" : "NO");
if (group.editable == NO) {
}
} failureBlock:^(NSError *error) {
NSLog(@"error adding album");
}];
}}