Save images with phimagemanager to custom album?

后端 未结 5 1510
北荒
北荒 2020-11-28 04:14

I am making an app that takes pictures with AVFoundation and I want to save them to a custom album that I can then query and show in my app. (I\'d prefer to not have them in

相关标签:
5条回答
  • 2020-11-28 05:03

    Answer in Objective-C and cleaned up a bit.

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

    The bit at the end with the UUID was something I found on another StackOverflow thread for creating a replacement for AssetURL property from an ALAsset.

    Note: See chris' comment below for more complete answer.

    0 讨论(0)
  • 2020-11-28 05:06

    I like to reuse the code I write so I decided to create an extension for PHPhotoLibrary where it is possible to use it like:

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

    Here is the code: https://gist.github.com/ricardopereira/636ccd0a3c8a327c43d42e7cbca4d041

    0 讨论(0)
  • 2020-11-28 05:11

    I improved on @ricardopereira and @ColossalChris code. Added video to the extension, and added another extension on top of PHAsset to get rid of the compilation errors. Works in Swift 2.1.

    Sample usage:

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

    Import both swift files: https://github.com/kv2/PHPhotoLibrary-PhotoAsset.swift

    It is usable in objective-c as long as you import the swift header for your target (see the ViewController.m file).

    0 讨论(0)
  • 2020-11-28 05:13

    As updated for Swift 2.1+ and for Video in case you are trying to do that and ended up here. Compare to the other answers for slight differences (such as using for Images rather than Video)

    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")
                   }
             }
     })
    
    0 讨论(0)
  • 2020-11-28 05:18

    This is how I do:

    At the top:

    import Photos
    
    var image: UIImage!
    var assetCollection: PHAssetCollection!
    var albumFound : Bool = false
    var photosAsset: PHFetchResult!
    var assetThumbnailSize:CGSize!
    var collection: PHAssetCollection!
    var assetCollectionPlaceholder: PHObjectPlaceholder!
    

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

    When saving the 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()
            })
        }
    

    Showing the images from that 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)
                    })
                }
            }
    
    0 讨论(0)
提交回复
热议问题