Curious101
Curious101

Reputation: 1748

PhotosFramework assign asset to album

I've looked at several examples and can't figure this one out. I feel I am missing something simple here.

In my app, I want to take an image in a specific album (ABC) and add it into another album (XYZ) that I created specifically for this app. Both the albums will be visible from IOS's default photo app.

I am successfully able to assign the image to album XYZ if I save another copy of the image. i.e. if I now go back to camera roll I will see two copies of the same image. One assigned to album ABC and another one to XYZ. This is not what I want. I have thousands of images that will be assigned to album XYZ and I don't want two copies to take up space unncessarily.

Here is my code that saves a copy of the image to new album:

-(void) saveImage:(UIImage*) imageToSave toCollection:(NSString *) collectionTitle forRowNumber:(long) rowNumber{

    NSLog(@"entered %s", __PRETTY_FUNCTION__);
    __block PHFetchResult *photosAsset;
    __block PHAssetCollection *collection;
    __block PHObjectPlaceholder *placeholder;

        // Find the album
    PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];

    fetchOptions.predicate = [NSPredicate predicateWithFormat:@"title = %@", collectionTitle];
                // this is how we get a match for album Title held by 'collectionTitle'

    collection = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAny options:fetchOptions].firstObject;

        // check if album exists
    if (!collection)
    {
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{

            NSLog(@" Album did not exist, now creating album: %@",collectionTitle);
                // Create the album
            PHAssetCollectionChangeRequest *createAlbum = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:collectionTitle];

            placeholder = [createAlbum placeholderForCreatedAssetCollection];

        } completionHandler:^(BOOL didItSucceed, NSError *error) {
            if (didItSucceed)
            {
                PHFetchResult *collectionFetchResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[placeholder.localIdentifier] options:nil];

                collection = collectionFetchResult.firstObject;
            }
        }];
    }

        // Save to the album
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{

        PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:imageToSave];

        placeholder = [assetRequest placeholderForCreatedAsset];
        photosAsset = [PHAsset fetchAssetsInAssetCollection:collection options:nil];

        PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection assets:photosAsset];

        [albumChangeRequest addAssets:@[placeholder]];

    } completionHandler:^(BOOL didItSucceed, NSError *error) {

        if (didItSucceed)
        {       // if YES


            NSLog(@" Looks like Image was saved in camera Roll as %@", placeholder.localIdentifier);
            NSLog(@"placeholder holds %@", placeholder.debugDescription );

        }
        else
        {
            NSLog(@"%@", error);
        }

    }];


}

I know that using the IOS Photos app you can assign an image to multiple albums and it does not create multiple copies.

Upvotes: 1

Views: 1061

Answers (1)

rickster
rickster

Reputation: 126167

You're getting a new image added to the library because you're explicitly requesting that a new image be added to the library:

PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:imageToSave];

If you have a PHAsset representing the original image, you can request to add that same asset to your second album. But because the code you've shared starts from a UIImage, you've lost the connection to the original asset.

Assuming you somewhere have that PHAsset, what you'd need looks something like this:

- (void)saveAsset:(PHAsset *)asset toCollectionNamed:(NSString *) collectionTitle {

    // Find the album
    PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
    fetchOptions.predicate = [NSPredicate predicateWithFormat:@"title = %@", collectionTitle];
    PHAssetCollection *collection = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAny options:fetchOptions].firstObject;

    // Combine (possible) album creation and adding in one change block
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        PHAssetCollectionChangeRequest *albumRequest;
        if (collection == nil) {
            // create the album if it doesn't exist
            albumRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:collectionTitle];
        } else {
            // otherwise request to change the existing album
            albumRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection];
        }
        // add the asset to the album
        [albumRequest addAssets:@[asset]];

    } completionHandler:^(BOOL success, NSError *error) {
        if (!success) {
            NSLog(@"error creating or adding to album: %@", error);
        }
    }];
}

Notice you don't need two PHPhotoLibrary performChanges blocks — you can create the album and add to it in the same change request.

Upvotes: 6

Related Questions