18

In iOS 8's Photos.framework, I'm trying to save a UIImage to the user's photo library, much in the same way you can long-press an image in Safari and choose the "Save Image". In iOS 7, this would be by just calling ALAssetLibrary's writeImageToSavedPhotosAlbum:metadata:completionBlock.

For iOS 8 we need to pick an asset collection to add a PHAsset to, but I can't figure out which PHAssetCollection is closest to just saving to the user's "camera roll" (even though there isn't one, really, in iOS 8)

[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
    PHAssetChangeRequest *newAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
    newAssetRequest.creationDate = time;
    newAssetRequest.location = location;

    PHObjectPlaceholder *placeholderAsset = newAssetRequest.placeholderForCreatedAsset;

    PHAssetCollectionChangeRequest *addAssetRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:WHICH_ASSET_COLLECTION];
    addAssetRequest addAssets:@[placeholderAsset];

} completionHandler:^(BOOL success, NSError *error) {
    NSLog(@"Success: %d", success);
}];

I tried accessing the "Recently Added" smart album, but it does not allow adding new content to it.

Rizwan Sattar
  • 1,578
  • 1
  • 14
  • 21

2 Answers2

30

You don't need to mess around with PHAssetCollection. Just add by doing:

    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:<#your photo here#>];
    } completionHandler:^(BOOL success, NSError *error) {
        if (success) {
            <#your completion code here#>
        }
        else {
            <#figure out what went wrong#>
        }
    }];
SushiGrass Jacob
  • 19,278
  • 1
  • 23
  • 39
  • in completion handler, how do you get the new asset? – Tejesh Alimilli Dec 29 '14 at 04:34
  • 1
    You use `@property(nonatomic, strong, readonly) PHObjectPlaceholder *placeholderForCreatedAsset` to, according to the docs, "Use this property if you need to reference the asset created by a change request within the same change block. For example, the following code, when included in a photo library change block, creates an asset and then adds it to a collection:" For more information on the Placeholder, I suggest reading the [docs](https://developer.apple.com/library/prerelease/ios/documentation/Photos/Reference/PHObjectPlaceholder_Class/index.html) on it. – SushiGrass Jacob Dec 29 '14 at 15:41
  • i already tried placeholder object. The example adds the placeholder object to album change request, but im maintaining an array of assets. Adding placeholder object to array didn't work. – Tejesh Alimilli Dec 29 '14 at 15:51
  • I would suggest opening a new questions so I can adequately see the issue and respond accordingly. – SushiGrass Jacob Dec 29 '14 at 17:05
  • 2
    nice touch adding placeholder tokens to your sample code! – djibouti33 May 28 '15 at 07:34
  • @SushiGrassJacob - How do I write the metadata to the photo using the PHAssetChangeRequest creationRequestForAssetFromImage. It doesn't seem to have a way to set GPSDictionary or EXIFDictionary. – user1191140 Aug 18 '15 at 02:34
  • @user1191140, please open a new question. – SushiGrass Jacob Aug 18 '15 at 21:35
6

Actually in 8.1 the Camera Roll is back. It is the smart album whose subtype is SmartAlbumUserLibrary.

matt
  • 447,615
  • 74
  • 748
  • 977
  • You have done very well, by the way, understanding what a placeholder is for. – matt Nov 13 '14 at 18:00
  • I think if he were to try to add it to that `ALAssetCollection` it would still be readonly and not be able to be added. Just adding it like in my answer will do what he desires. – SushiGrass Jacob Nov 13 '14 at 18:07
  • @SushiGrassJacob The Camera Roll is writable. – matt Nov 13 '14 at 19:01
  • Apparently Swift has SmartAlbumUserLibrary, but the doc for objective-C doesn't show it being present: typedef enum : NSInteger { ... PHAssetCollectionSubtypeSmartAlbumBursts = 207, PHAssetCollectionSubtypeSmartAlbumSlomoVideos = 208, PHAssetCollectionSubtypeAny = NSIntegerMax } PHAssetCollectionSubtype; – Todd Hoff Jan 21 '15 at 00:46
  • @ToddHoff The _docs_ have not been revised, but that's irrelevant; it's in the _header_: `PHAssetCollectionSubtypeSmartAlbumUserLibrary = 209` – matt Jan 21 '15 at 01:03
  • Thanks matt. Silly me for thinking the docs were generated from the code :-) – Todd Hoff Jan 22 '15 at 07:10