![](/img/trans.png)
[英]Image save issue in custom album as well as default Camera Roll in iphone
[英]iPhone - How to create a custom album and give custom names to photos in camera roll programmatically?
我正在開發一個 iPhone 照片應用程序,所以我需要在相機膠卷中創建一個名為“我的相冊”的單獨相冊,我需要在新創建的目錄中使用自定義名稱保存我的 UIImageView 圖像,例如“My Image.png” .
我怎樣才能做到這一點?
您可以使用 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);
}
}];
由於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
庫。
要在該相冊上創建新的照片資產,請使用PHAssetChangeRequest.creationRequestForAsset(from:
) 。
// 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>
創建新相冊:
/// Create album with given title
/// - Parameters:
/// - title: the title
/// - completionHandler: the completion handler
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 album with given title
/// - Parameters:
/// - title: the title
/// - completionHandler: the completion handler
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)
})
}
}
}
它從 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");
}];
你可以試試我下面的為 iOS 7 和 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");
}];
}}
/// 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
您可以先將自定義名稱的圖像保存到沙箱,然后將其保存到相冊,它對我有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.