ios iPhone - 如何以编程方式创建自定义相册并为相机胶卷中的照片指定自定义名称?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12152430/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:54:41  来源:igfitidea点击:

iPhone - How to create a custom album and give custom names to photos in camera roll programmatically?

iphoneioscameransfilemanager

提问by sachi

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.

我正在开发一个 iPhone 照片应用程序,所以我需要在相机胶卷中创建一个名为“我的相册”的单独相册,我需要在新创建的目录中使用自定义名称保存我的 UIImageView 图像,例如“My Image.png” .

How can i do this?

我怎样才能做到这一点?

采纳答案by NDY

You can create a custom album and add an image pretty easy with these lines of code in iOS:

您可以使用 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);
    }
}];

回答by ricardopereira

Since the AssetsLibraryis deprecated, please use the Photosframework instead (iOS 8 and later).

由于AssetsLibrary弃用,请改用该Photos框架(iOS 8 及更高版本)。

// 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 PHPhotoLibraryobject 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.

您可以使用共享PHPhotoLibrary对象来创建新照片,但不能为它们指定特定名称,因为您将使用需要由Photos.app管理的资产。每个资产都有特定的属性。您可以获取对象、请求更改、资产/缩略图加载和缓存等。

To create a custom album, please use the PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle:).

要创建自定义相册,请使用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 Photoslibrary.

别忘了去import Photos图书馆。

To create a new photo asseton that album, please use the PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle:).

要在该相册上创建新的照片资产,请使用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 10and above we also need to add entry for access in the target .plist file for "Privacy - Photo Library Usage Description":

从 iOS 10及更高版本开始,我们还需要在目标 .plist 文件中为“隐私 - 照片库使用说明”添加访问条目:

<key>NSPhotoLibraryUsageDescription</key>
<string>Access to photos is needed to provide app features</string>

回答by Vaibhav Sharma

It was working from since iOS 5.0.
Please import AssetsLibrary/AssetsLibrary.h

它从 iOS 5.0 开始工作。
请导入 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");
}];

回答by nslllava

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: [
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)
            })
        }
    }
}
.localIdentifier], options: nil) } album = collectionFetchResult?.firstObject } completionHandler(album) }) } }

Get an album with with a specified name:

获取具有指定名称的专辑:

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 { [
/// Save images or videos(保存图片或视频)(kUTTypeImage, kUTTypeMovie)
/// Add to album if specified album name, and create album if needed
/// @params mediaArray UIImage, fileURL for a image or video
+ (void)_saveMediaArray:(NSArray *)mediaArray
                options:(LAImageSaverOptions *)options
             completion:(void (^)(NSError * _Nullable err))completion
{
    NSInteger __block count = 0;

    [PHPhotoLibrary.sharedPhotoLibrary performChanges:^{

        // Create album if needed
        PHAssetCollectionChangeRequest *assetCollectionChangeRequest = nil;
        NSMutableArray<PHObjectPlaceholder *> *assetChangeRequestPlaceholders = nil;
        if (options.targetAlbumName.length > 0) {
            assetChangeRequestPlaceholders = [NSMutableArray arrayWithCapacity:mediaArray.count];

            PHFetchOptions *fetchOptions = PHFetchOptions.new;
            //fetchOptions.includeAssetSourceTypes = PHAssetSourceTypeUserLibrary;
            fetchOptions.predicate = [NSPredicate predicateWithFormat:@"localizedTitle = %@", options.targetAlbumName]; // 不能用 block 形式的 predicate
            PHAssetCollection * assetCollection = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:fetchOptions].firstObject;
            if (nil == assetCollection) {
                assetCollectionChangeRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:options.targetAlbumName];
            } else {
                assetCollectionChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
            }
         }

        // Save images
        for (id item in mediaArray) {
            PHAssetChangeRequest *assetChangeRequest = nil;
            // image object
            if ([item isKindOfClass:UIImage.class]) {
                UIImage *image = (UIImage *)item;
                assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
                [assetChangeRequestPlaceholders addObject:assetChangeRequest.placeholderForCreatedAsset];
                ++count;
                continue;
            }

            // file url for image or movie
            NSURL *fileURL = (NSURL *)item;
            if ([item isKindOfClass:NSURL.class] && fileURL.isFileURL) {
                NSString *extension = fileURL.pathExtension;
                if (extension.length == 0) {
                    NSLog(@"illegal fileURL(no path extension): %@", fileURL);
                    continue; // illegal file url
                }
                CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL);
                BOOL isImage = false;
                BOOL isVideo = false;
                if (nil != uti && CFStringGetLength(uti) > 0) {
                    isImage = UTTypeConformsTo(uti, kUTTypeImage);
                    isVideo = UTTypeConformsTo(uti, kUTTypeMovie); // kUTTypeVideo, kUTTypeAudiovisualContent
                }
                if (isImage) {
                    assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:fileURL];
                    [assetChangeRequestPlaceholders addObject:assetChangeRequest.placeholderForCreatedAsset];
                    ++count;
                } if (isVideo) {
                    assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:fileURL];
                    [assetChangeRequestPlaceholders addObject:assetChangeRequest.placeholderForCreatedAsset];
                    ++count;
                } else {
                    NSLog(@"illegal fileURL(neither image nor movie): %@", fileURL);
                    continue; // illegal file url
                }
            }
        }

        // add to album if needed
        [assetCollectionChangeRequest addAssets:assetChangeRequestPlaceholders];

    } completionHandler:^(BOOL success, NSError * _Nullable error) {

        // not in main thread 
        dispatch_async(dispatch_get_main_queue(), ^{
            completion(error);
        });
    }];
}
] as NSArray } ?? NSArray() let albumChangeRequest = album.flatMap { PHAssetCollectionChangeRequest(for:
@interface LAImageSaverOptions : NSObject

/// to show alert controller on the hostVC
@property(nonatomic, weak, null_resettable) UIViewController *hostVC;


/// total progress
@property (nonatomic, strong, null_resettable) NSProgress *progress;

// album name for saving images
@property (nonatomic, copy, nullable) NSString *targetAlbumName;

@end
) } albumChangeRequest?.addAssets(assets) }, completionHandler: { (success, error) in completionHandler(success, error) }) } } }

And save a photo to a Photos album:

并将照片保存到相册:

#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");
    }];
}}

回答by DawnSong

##代码##

By the way, you can do more about LAImageSaverOptions

顺便说一下,你可以做更多关于 LAImageSaverOptions

##代码##

回答by Gaurav

You can try My below Method for Create Album for iOS 7 and iOS 8

你可以试试我下面的为 iOS 7 和 iOS 8 创建相册的方法

##代码##