Je crée une application qui prend des photos avec AVFoundation et je souhaite les enregistrer dans un album personnalisé que je peux ensuite interroger et afficher dans mon application. (Je préférerais ne pas les avoir dans le rouleau de photos général, à moins que l'utilisateur ne le souhaite) Je ne trouve rien qui montre comment faire cela dans Swift ... ou même du tout. Y a-t-il une façon différente de faire cela?
J'ai trouvé cet exemple sur SO mais cela n'a aucun sens pour moi et je ne peux pas le faire fonctionner.
func savePhoto() {
var albumFound : Bool = false
var assetCollection: PHAssetCollection!
var photosAsset: PHFetchResult!
var assetThumbnailSize:CGSize!
// Create the album if does not exist (in viewDidLoad)
if let first_Obj:AnyObject = collection.firstObject{
//found the album
self.albumFound = true
self.assetCollection = collection.firstObject as PHAssetCollection
}else{
//Album placeholder for the asset collection, used to reference collection in completion handler
var albumPlaceholder:PHObjectPlaceholder!
//create the folder
NSLog("\nFolder \"%@\" does not exist\nCreating now...", albumName)
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
let request = PHAssetCollectionChangeRequest.creationRequestForAssetCollectionWithTitle(albumName)
albumPlaceholder = request.placeholderForCreatedAssetCollection
},
completionHandler: {(success:Bool, error:NSError!)in
NSLog("Creation of folder -> %@", (success ? "Success":"Error!"))
self.albumFound = (success ? true:false)
if(success){
let collection = PHAssetCollection.fetchAssetCollectionsWithLocalIdentifiers([albumPlaceholder.localIdentifier], options: nil)
self.assetCollection = collection?.firstObject as PHAssetCollection
}
})
}
let bundle = NSBundle.mainBundle()
let myFilePath = bundle.pathForResource("highlight1", ofType: "mov")
let videoURL:NSURL = NSURL.fileURLWithPath(myFilePath!)!
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0), {
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
//let createAssetRequest = PHAssetChangeRequest.creationRequestForAssetFromImage
let createAssetRequest = PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(videoURL)
let assetPlaceholder = createAssetRequest.placeholderForCreatedAsset
let albumChangeRequest = PHAssetCollectionChangeRequest(forAssetCollection: self.assetCollection, assets: self.photosAsset)
albumChangeRequest.addAssets([assetPlaceholder])
}, completionHandler: {(success, error)in
dispatch_async(dispatch_get_main_queue(), {
NSLog("Adding Image to Library -> %@", (success ? "Sucess":"Error!"))
//picker.dismissViewControllerAnimated(true, completion: nil)
})
})
})
}
Toute aide/explication serait géniale!
Voici comment je fais:
Au sommet:
import Photos
var image: UIImage!
var assetCollection: PHAssetCollection!
var albumFound : Bool = false
var photosAsset: PHFetchResult!
var assetThumbnailSize:CGSize!
var collection: PHAssetCollection!
var assetCollectionPlaceholder: PHObjectPlaceholder!
Création de l'album:
func createAlbum() {
//Get PHFetch Options
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", "camcam")
let collection : PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .Any, options: fetchOptions)
//Check return value - If found, then get the first album out
if let _: AnyObject = collection.firstObject {
self.albumFound = true
assetCollection = collection.firstObject as! PHAssetCollection
} else {
//If not found - Then create a new album
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
let createAlbumRequest : PHAssetCollectionChangeRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollectionWithTitle("camcam")
self.assetCollectionPlaceholder = createAlbumRequest.placeholderForCreatedAssetCollection
}, completionHandler: { success, error in
self.albumFound = success
if (success) {
let collectionFetchResult = PHAssetCollection.fetchAssetCollectionsWithLocalIdentifiers([self.assetCollectionPlaceholder.localIdentifier], options: nil)
print(collectionFetchResult)
self.assetCollection = collectionFetchResult.firstObject as! PHAssetCollection
}
})
}
}
Lors de l'enregistrement de la photo:
func saveImage(){
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
let assetRequest = PHAssetChangeRequest.creationRequestForAssetFromImage(self.image)
let assetPlaceholder = assetRequest.placeholderForCreatedAsset
let albumChangeRequest = PHAssetCollectionChangeRequest(forAssetCollection: self.assetCollection, assets: self.photosAsset)
albumChangeRequest!.addAssets([assetPlaceholder!])
}, completionHandler: { success, error in
print("added image to album")
print(error)
self.showImages()
})
}
Affichage des images de cet album:
func showImages() {
//This will fetch all the assets in the collection
let assets : PHFetchResult = PHAsset.fetchAssetsInAssetCollection(assetCollection, options: nil)
print(assets)
let imageManager = PHCachingImageManager()
//Enumerating objects to get a chached image - This is to save loading time
assets.enumerateObjectsUsingBlock{(object: AnyObject!,
count: Int,
stop: UnsafeMutablePointer<ObjCBool>) in
if object is PHAsset {
let asset = object as! PHAsset
print(asset)
let imageSize = CGSize(width: asset.pixelWidth, height: asset.pixelHeight)
let options = PHImageRequestOptions()
options.deliveryMode = .FastFormat
imageManager.requestImageForAsset(asset, targetSize: imageSize, contentMode: .AspectFill, options: options, resultHandler: {(image: UIImage?,
info: [NSObject : AnyObject]?) in
print(info)
print(image)
})
}
}
Répondez en Objective-C et nettoyez un peu.
__block PHFetchResult *photosAsset;
__block PHAssetCollection *collection;
__block PHObjectPlaceholder *placeholder;
// Find the album
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.predicate = [NSPredicate predicateWithFormat:@"title = %@", @"YOUR_ALBUM_TITLE"];
collection = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
subtype:PHAssetCollectionSubtypeAny
options:fetchOptions].firstObject;
// Create the album
if (!collection)
{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCollectionChangeRequest *createAlbum = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:@"YOUR_ALBUM_TITLE"];
placeholder = [createAlbum placeholderForCreatedAssetCollection];
} completionHandler:^(BOOL success, NSError *error) {
if (success)
{
PHFetchResult *collectionFetchResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[placeholder.localIdentifier]
options:nil];
collection = collectionFetchResult.firstObject;
}
}];
}
// Save to the album
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:[UIImage imageWithData:imageData]];
placeholder = [assetRequest placeholderForCreatedAsset];
photosAsset = [PHAsset fetchAssetsInAssetCollection:collection options:nil];
PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection
assets:photosAsset];
[albumChangeRequest addAssets:@[placeholder]];
} completionHandler:^(BOOL success, NSError *error) {
if (success)
{
NSString *UUID = [placeholder.localIdentifier substringToIndex:36];
self.photo.assetURL = [NSString stringWithFormat:@"assets-library://asset/asset.PNG?id=%@&ext=JPG", UUID];
[self savePhoto];
}
else
{
NSLog(@"%@", error);
}
}];
Le bit à la fin avec l'UUID était quelque chose que j'ai trouvé sur un autre thread StackOverflow pour créer un remplacement pour la propriété AssetURL à partir d'un ALAsset.
Remarque: Voir le commentaire de chris ci-dessous pour une réponse plus complète.
J'aime réutiliser le code que j'écris, j'ai donc décidé de créer une extension pour PHPhotoLibrary où il est possible de l'utiliser comme:
PHPhotoLibrary.saveImage(photo, albumName: "Trip") { asset in
guard let asset = asset else {
assert(false, "Asset is nil")
return
}
PHPhotoLibrary.loadThumbnailFromAsset(asset) { thumbnail in
print(thumbnail)
}
}
Voici le code: https://Gist.github.com/ricardopereira/636ccd0a3c8a327c43d42e7cbca4d041
Comme mis à jour pour Swift 2.1+ et pour la vidéo au cas où vous essayez de le faire et vous vous retrouvez ici. Comparez avec les autres réponses pour de légères différences (comme utiliser pour des images plutôt que de la vidéo)
var photosAsset: PHFetchResult!
var collection: PHAssetCollection!
var assetCollectionPlaceholder: PHObjectPlaceholder!
//Make sure we have custom album for this app if haven't already
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", "MY_APP_ALBUM_NAME")
self.collection = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .Any, options: fetchOptions).firstObject as! PHAssetCollection
//if we don't have a special album for this app yet then make one
if self.collection == nil {
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
let createAlbumRequest : PHAssetCollectionChangeRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollectionWithTitle("MY_APP_ALBUM_NAME")
self.assetCollectionPlaceholder = createAlbumRequest.placeholderForCreatedAssetCollection
}, completionHandler: { success, error in
if success {
let collectionFetchResult = PHAssetCollection.fetchAssetCollectionsWithLocalIdentifiers([self.assetCollectionPlaceholder.localIdentifier], options: nil)
print(collectionFetchResult)
self.collection = collectionFetchResult.firstObject as! PHAssetCollection
}
})
}
//save the video to Photos
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
let assetRequest = PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(self.VIDEO_URL_FOR_VIDEO_YOU_MADE!)
let assetPlaceholder = assetRequest!.placeholderForCreatedAsset
self.photosAsset = PHAsset.fetchAssetsInAssetCollection(self.collection, options: nil)
let albumChangeRequest = PHAssetCollectionChangeRequest(forAssetCollection: self.collection, assets: self.photosAsset)
albumChangeRequest!.addAssets([assetPlaceholder!])
}, completionHandler: { success, error in
if success {
print("added video to album")
}else if error != nil{
print("handle error since couldn't save video")
}
}
})
J'ai amélioré le code @ricardopereira et @ColossalChris. Ajout de la vidéo à l'extension et ajout d'une autre extension au-dessus de PHAsset pour supprimer les erreurs de compilation. Fonctionne dans Swift 2.1. Exemple d'utilisation:
#import "Yourtargetname-Swift.h"//important!
NSURL *videoURL = [[NSURL alloc] initFileURLWithPath:PATH_TO_VIDEO];
[PHPhotoLibrary saveVideo:videoURL albumName:@"my album" completion:^(PHAsset * asset) {
NSLog(@"success");
NSLog(@"asset%lu",(unsigned long)asset.pixelWidth);
}];
Importez les deux fichiers Swift: https://github.com/kv2/PHPhotoLibrary-PhotoAsset.Swift
Il est utilisable dans objective-c tant que vous importez l'en-tête Swift pour votre cible (voir le fichier ViewController.m ).