Reputation: 1748
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
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