web-dev-qa-db-ja.com

iPhone-プログラムでカスタムアルバムを作成し、カメラロールの写真にカスタム名を付ける方法は?

IPhoneの写真アプリケーションを開発しているので、カメラロールに「MyAlbum」という名前の別のアルバムを作成し、新しく作成したディレクトリ内に「MyImage.png」などのカスタム名でUIImageView画像を保存する必要があります。 。

これどうやってするの?

19
sachi

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);
    }
}];
16
NDY

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)
})

共有PHPhotoLibraryオブジェクトを使用して新しい写真を作成できますが、アセットを操作するため、特定の名前を付けることはできません。 Photos.appで管理する必要があります。各アセットには特定のプロパティがあります。オブジェクトのフェッチ、変更のリクエスト、アセット/サムネイルの読み込みとキャッシュなどを行うことができます。

カスタムアルバムを作成するには、 PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: を使用してください。

簡単な例:

// 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
        }
    })
}

import Photosライブラリを忘れないでください。

そのアルバムに新しい写真アセットを作成するには、 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
        }
    })
}

更新:

写真ライブラリを使用できるようにするには、アクセスをリクエストする必要があります。

PHPhotoLibrary.requestAuthorization { status in
     switch status {
     ...
}

iOS 10以降では、「プライバシー-フォトライブラリの使用法の説明」のターゲット.plistファイルにアクセスするためのエントリも追加する必要があります。

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

IOS5.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");
}];
7
Vaibhav Sharma

新しいアルバムを作成します。

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)
        })
    }
}

指定された名前のアルバムを取得します。

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)
            })
        }
    }
}

そして、写真をフォトアルバムに保存します。

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)
            })
        }
    }
}
3
xcocoader

IOS7およびiOS8用のアルバムを作成するための以下の方法を試すことができます

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

ちなみに、あなたはLAImageSaverOptionsについてもっとすることができます

@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
0
DawnSong