Hi this is Marin - the author of Touch Code Magazine, I hope you are enjoying my tutorials and articles. Also if you need a bright iPhone developer overseas contact me - I do contract work. Here's my LinkedIn profile
iOS5: Saving photos in custom photo album (+category for download)

Custom photo albums in iOS5

iOS5 features new APIs in the AssetsLibrary framework which give you the opportunity to manage your app’s own photo album inside the user’s photo library. That is a logical step from Apple since photo applications market is booming and users want to have their photos organized by the application they were created with. (I released 4 photo apps to date, 5th in review – so I have pretty good overview on photo apps)

I wanted to include a ALAssetsLibrary API chapter in “iOS5 by Tutorials” but I was experience problems with the assets framework until the very launch of iOS5 (and after) so I decided not to include such chapter in the book. It looks like the combination of the iCloud photo stream, Core Data managed photo library and 3rd party apps read/write access at the same time is giving Apple hard time – I’m looking forward to 5.0.1 to see if the problems would be fixed.

Without further ado – iOS5 allows you to create and delete albums in the user photo library and add pictures from the camera roll to those albums too. Let’s have a look.

Custom photo album category for ALAssetsLibrary

Unfortunately browsing through the new assets APIs you won’t find a single method, which will create or access your custom album and save an image inside. And honestly this is all I would need when creating a photo app – something easy to call and pass a UIImage to.

So while creating my latest app (Fun Photo Booth – to come out in the next days) I crafted a simple category add-on for ALAssetsLibrary and in this tutorial I’ll show you how to use for your own photo apps (free code download included of course)

The method we will use from the category is the following:

-(void)saveImage:(UIImage*)image
         toAlbum:(NSString*)albumName
withCompletionBlock:(SaveImageCompletion)completionBlock;

Easy peasy. Your app should create a UIImage by doing its special magic and will just need to pass it to this method along with the album name and a block to handle the end of the saving process. I think this should be as simple as it gets. Let’s see this in action by creating a simple project and use the category.

Building a demo with own photo album

Start by creating a single view project in Xcode – name it “CustomPhotoAlbumDemo”. Add the AssetsLibrary.framework to the project (I’m going quicker over these steps ok?) Download the ALAssetsLibrary+CustomPhotoAlbum code from here: ALAssetsLibrary_CustomPhotoAlbum.zip and copy the 2 files for the category inside your Xcode project. Setup is done.

Now open up the XIB file in the project and setup a single button like so:

Open up your view controller header file and add this import at the top:

#import <AssetsLibrary/AssetsLibrary.h>

and a property to keep hold of the assets library:

@property (strong, atomic) ALAssetsLibrary* library;

last you’ll need the class to be a UIImagePickerController delegate, so after “UIViewController” on the same line add:

<UIImagePickerControllerDelegate>

That should be about right. Open the implementation file now. Just below the @implementation line synthesize the library property:

@synthesize library;

NB! When you work with ALAssetsLibrary it represents a snapshot of the assets on the device, i.e. if you have different instances of ALAssetsLibrary they may get out of sync, not to mention other horrible discrepancies, which seems to happen on iOS5. So, advice in Apple dev forums is – have a single instance of the library and make it a strong property, make sure you never loose it and work only with it. I find this advice immensely helpful, although it doesn’t really solve all problems, but does most

So, we have the library in a property – let’s also take care of initializing it. Lookup viewDidLoad and viewDidUnload and replace them with:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.library = [[ALAssetsLibrary alloc] init];
}
 
- (void)viewDidUnload
{
    self.library = nil;
    [super viewDidUnload];
}

Few more steps and we’ll be ready with our photo app demo. I hope you are familiar with using the camera controller, as I won’t go into details. In short – you make an instance of a controller, which basically takes a photo for you and serves it back to a delegate of your choice. So add the method to take the photo:

- (IBAction)takePhoto
{
    UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
    imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
	imagePickerController.editing = YES;
    imagePickerController.delegate = (id)self;
 
    [self presentModalViewController:imagePickerController animated:YES];
}

OK. Let’s connect the UI with the code. Open the XIB file again. While holding the “Ctrl” key drag with the mouse from the button to File’s Owner and from the popup menu choose “takePhoto”:

OK. If you want you can run the app and see if the Camera interface pops up when you tap the button (That won’t work in the Simulator, give it a try on the device)

Now when the user takes a photo and decides to use it, the “imagePickerController:didFinishPickingImage:editingInfo:” method on your view controller (or other delegate) will be called. So you will get a UIImage instance, do your magic on it (if any) and then proceed to saving. In our demo there’ll be no magic applied to the image, so we will just save in a custom photo album the photo taken. (If you want to learn more about Image filters and such with the new for iOS5 CoreImage, have a look at the “iOS5 by Tutorials” book)

Let’s implement the callback:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
    [self.library saveImage:image toAlbum:@"Touch Code Magazine" withCompletionBlock:^(NSError *error) {
        if (error!=nil) {
            NSLog(@"Big error: %@", [error description]);
        }
    }];
 
    [picker dismissModalViewControllerAnimated:NO];
}

So this is the category method, which takes in a UIImage, the name of the album and a completion block. The album may or may not exist already. If it does not, it will be created on the fly (yay). And the completion block will receive an NSError instance if there was an error in any step of the process.

That’s all about saving to a custom photo album with the ALAssetsLibrary+CustomPhotoAlbum category. If you’re interested have a look at the category code to see what’s going on behind the scenes.

Now to wrap up with the demo project code, let’s just add this one method for when the user cancels the camera UI:

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [picker dismissModalViewControllerAnimated:NO];
}

Let’s run the project; initially I have 2 albums in my photo library:

Then I take a photo by tapping “Take photo” in the app:

And after the camera UI is gone, let’s switch again to the Photos app on the device:

Now, you can also play further with the new AssetsLibrary APIs – you can now edit files inside your own albums (yes, you read correct, not open and save copies, but edit files – though only the ones your app did create), but the category at hand should cover the basic needs of any photo app.

Here’s the complete Xcode project of the demo app: CustomAlbumDemo (it includes the category source code files)

I hope that’ll be helpful to you and also do let me know what other iOS5 features are you interested to read about.

Marin

The post was originally published on the following URL: http://www.touch-code-magazine.com/ios5-saving-photos-in-custom-photo-album-category-for-download/

 

  ·

 


Marin Todorov

is an independent iOS developer and publisher. He's got more than 18 years of experience in a dozen of languages and platforms. This is his writing project.
» Contact    » Add Marin on Google+

  1. Lector on Monday 7, 2011

    Well, looking at the category code i think you saved me a few days… actually i’m not sure if i could get this to work without any help.

    Thank You! This was really helpful :)

  2. [...] smooth enough already.If you would like to add this feature to your iOS app, you can have a look at this tutorial I wrote about it (it features also a free source code download)Integration with the new iOS5 Twitter UIRight now the app is compatible with iOS 5.0 and iOS 4.x, so [...]

  3. Antonio on Monday 7, 2011

    Fantastic code!

    Would just wrap all the code in -(void)addAssetURL:(NSURL*)assetURL toAlbum:(NSString*)albumName withCompletionBlock:(SaveImageCompletion)completionBlock method – ALAssetsLibrary+CustomPhotoAlbum.m with the following:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

    //Added the 1 second sleep to this separate thread to ensure the group is Editable.
    //Might not be editable because of the previous method
    sleep(1);

    __block BOOL albumWasFound = NO;
    ……

    });
    }

    This to ensure that the group is editable when adding the asset to the group ( [group addAsset: asset]; )

  4. Patrick on Monday 7, 2011

    Hi, great tutorial!!!

    Sorry if this is a easy question, but how would you go about modifying it so that the image saved to the photo library comes from a URL?

  5. Marin on Monday 7, 2011

    Hey Patrick, here’s a google search which will help you loading images from URL: http://www.google.com/search?client=safari&rls=en&q=stack+overflow+objective+c+save+photo+from+URL&ie=UTF-8&oe=UTF-8

  6. Steven on Monday 7, 2011

    Hi!

    We tried the code (and it worked ;-) , but… You can only add 1 photo to the custom photo album. If you exit and open the app again and save another image, it will not show up in the custom album.

    Is it correct that a custom album is only editable in the same session?

    (Btw, I tried the Xmas Both app and it has the same ‘problem’)..

    Thx!
    Steven

  7. Marin on Monday 7, 2011

    hi Steven, that’s definitely not how the code should behave – I dont have it here on my devices… fun photo booth also is fine. did u try that on different devices?

  8. Steven on Monday 7, 2011

    Hi Marin,

    OK, I will check this again on different devices. So, for my understanding, is it also possible to save photos into albums that were not created by the app? (i.e. do you have the rights to modify all albums on the iPhone?)

    And finally, can you delete photos from an album?

    I will check an let you know tomorrow!

  9. Steven on Monday 7, 2011

    I Checked fun photo booth, it’s strange,most photos indeed end up in that album, but not all. Can’t see why some do and some don’t. But anyway, it is clearly possible to have multiple photos stored in an album created with the app.

    Question is: Can you store photos in albums that were not created with the app? And/or can you delete photos from such an album?

    Your help is much appreciated!

    Steven

  10. Till on Monday 7, 2011

    Hi
    thanks for this great piece of code.

    I implemented it. The only thing that’s starge is that it saves the image to the custom album AND the standard iphone album…?

    Do you know what could cause this?

    Thanks in advance.

  11. Marin on Monday 7, 2011

    hey Till glad it worked – actually the photos are always saved to the camera roll – you just assign them to albums, ie. the album is kind of like a view or a filter towards the camera roll … hope that helps, Marin

  12. Till on Monday 7, 2011

    Got it, makes sense!

    Thanks a lot.

  13. pawan Kumar on Monday 7, 2011

    i am using this code and ia have a n error in this code error is :

    wait_fences: failed to receive reply: 10004003

    used code:
    [self.library saveImage:imgNew toAlbum:@"Game" withCompletionBlock:^(NSError *error) {
    if (error!=nil) {
    NSLog(@"Big error: %@", [error description]);
    }
    }];

  14. Christian on Monday 7, 2011

    Hi,

    thanks for sharing your nice category. I also experience the behaviour that saving images to my custom library does sometimes work, sometimes not…

    Did you gain any insight why and might want to share that with us?

    Thx a lot.

  15. RW on Monday 7, 2011

    Great tutorial I love the idea of custom libraries for photos.

    is there a way to do this in storyboards? I’d like to include this camera function within a model view and editable data fields around it. Any suggestions would be great

  16. RW on Monday 7, 2011

    This is a great tutorial…but

    is there anyway to do this within storyboards in Xcode 4.2 ?
    I am building a deep table view ap (about 4 tableviews) that needs this ability on the deepest level.

  17. Marin on Monday 7, 2011

    Hey – can’t say I haven’t been really using storyboards myself (using 15″ laptop, so no way to go for storyboards)
    However http://touch-code-magazine.com/iOS5ByTutorials is always good resource on everything iOS5 – including 2 chapters on everything Storyboards, this might be of help

    best, Marin

  18. Bogdan on Monday 7, 2011

    Thanks a lot for this category. It was very helpfull but i have a question?
    I don’t understand this line, can you please explain why it is used?
    __weak ALAssetsLibrary* weakSelf = self;

  19. Marin on Monday 7, 2011

    since you use the assets library inside the block, ARC will complain on compile time that there’s a retain cycle. When you have this – you just make a weak copy of your object (as in the line of code you’re asking about). Marin

  20. gerald on Monday 7, 2011

    Hi Marin,
    Thanks so much for the category. I’m using it in the project that I am working on and it works beautifully… most of the time. I noticed in an above comment that someone else was having trouble with this category not always saving to the specified album. Have you (or anyone reading this comment) come across an explanation/solution?

  21. Paul on Monday 7, 2011

    Hi Marin!

    Great!! One question. It’s possible to save image to app’s own photo album without duplicate to Camera Roll? Thanks :)

  22. Marin on Monday 7, 2011

    no paul, you always save them in the camera roll and the albums are kind of a “view” filter to the roll

  23. Ondrej on Monday 7, 2011

    So I have implemented the category and getting the strange sometimes saved, sometimes not behaviour. Here are my observations:

    It saves the image for the first time
    It saves the image if you restart or just leave the app (background)
    If you save two photos in the row, it saves it but to the Camera Roll only

    It looks like that there is something like a finalize statement missing or it’s just a new Apple bug … dunno :(

  24. Arun on Monday 7, 2011

    Hi All,

    I am trying to erase an image using IKImageview in OSX.. Since last one month i am trying to do this but still not able to erase…Its urgent for me …if anybody know pls pls pls help me ….

  25. Mithun Dhali on Monday 7, 2011

    Firstly, thanks a lot for the example.

    I found a race condition (it was giving me problem).

    // group is coming from ALAssetsLibraryGroupsEnumerationResultsBlock
    [self assetForURL: assetURL resultBlock:^(ALAsset *asset) {

    // NOTE: This is called in a new thread. If enclosing ALAssetsLibraryGroupsEnumerationResultsBlock completes before this starts, a race condition is possible as group may be already released.
    [group addAsset: asset];

    //run the completion block
    completionBlock(nil);
    }

  26. Chris O on Monday 7, 2011

    I was having trouble getting consistent results using this code, stumbled upon this S.O. post that helped me to solve that problem:

    http://stackoverflow.com/questions/7937876/alassetsgroup-becomes-invalid

    Turns out the ALAssetGroup object will not be nil, but it’s properties will be set to nil whenever the ALAssetLibrary decides, even immediately after passing you the object in your block. So… do a check to make sure that the properties of the group object are not nil before you call addAsset. You may need to refactor the code and try enumerating groups again and again until it provides you a group object that isn’t invalidated.

    Try using something like this to detect the invalidated group:

    if ([group valueForProperty:ALAssetsGroupPropertyURL] == nil)
    {
    NSLog(@”group properties are nil!”);
    } else {
    [group addAsset:asset];
    }

    I believe this is why people with comments here have had inconsistent results in their projects – because they go to addAsset to a group that has had it’s properties set to nil. So in effect the addAsset is not taking place. The image gets saved to Camera Roll maybe, but not added to the custom album.

    Good luck to anyone with the same problem finding a custom solution that works for them.

    Thanks again, Apple.

  27. Andrew on Monday 7, 2011

    @Chris O: thanks for posting that, I’m getting nil still sometimes. I’m guessing your code and idea is to catch that problem and assign a value? If so, would you mind sharing your code on how you do this? I’ve been trying for days.

    Cheers.

  28. Pierre-Loup on Monday 7, 2011

    Very useful !
    Under which licence is the code ?
    Thanks !

  29. Marin on Monday 7, 2011

    Hi Pierre, I didn’t really think about that, but you can think of it as MIT licensed .. free to use, attribution not required. Marin

  30. myr0 on Monday 7, 2011

    hi there!

    i tried that code on my iPhone and it will neither create a new library or safe a picture inside, if i create it myself, nor safe any picture in the camera roll.
    i’m using ios 5.1.
    thanks for help in advice!

    myr0

  31. neeraj on Monday 7, 2011

    Hi,

    Thanks a lot for the code. But i was having a bit of a problem. I want to save the url of the saved image and pass it back to the calling class. (not using a global variable)

    The delegate thing for a callback is not really working. can you suggest a method

  32. Jaminyah on Monday 7, 2011

    Folks, after sending 3 days trying to get a custom photo album created and photo saved to the album here are my findings:

    Geo-location is required for the example app to work. Not sure why. The app does give an error output related to requesting your location if you opt to not approve using your location. This error output is shown on the Xcode output display when the iDevice is connected to your Xcode IDE.

    With an internet connection active and approving geo-location when prompted, the app will create a custom album as well as save photos to both the Camera Roll and your custom album.

    I am using an iPod Touch 4G and did not turn on WiFi and denied geo-location because I did not know it was significant. So for three days I struggled to get the app working.

    These are my findings. Thanks for contributing this tutorial and the code.

  33. Rajneesh on Monday 7, 2011

    Its saving photos both in custom album and apple saved photo album,
    i only want to save in my custom album not in saved photo, how to do this.

  34. Marin on Monday 7, 2011

    Rajneesh all photos are saved ONLY in the “saved photos” album – your custom albums are more of a filter, which shows just certain photos of all saved ones.

  35. Joyh on Monday 7, 2011

    Thank you! You saved my ass.

  36. northtree on Monday 7, 2011

    Thank you for your sharing.

    Is it posible to set the latest saved photos as the custom album cover? Now this library only sets the first photo as album cover.

  37. northtree on Monday 7, 2011

    Hi Marin,

    The display of post date in your blog is wrong. All display “on Monday 7, 2011″.

  38. Praveen on Monday 7, 2011

    Hi Marin,
    That was a good one. Can you create nested custom albums ?

  39. julien on Monday 7, 2011

    Awesome Marin, thank you very much…

  40. Jeff on Monday 7, 2011

    Hey

    I use this code in my project

    but it doesn’t work

    it can’t create a new album and just save the image to the camera album

    can this code use in ios5.1 version?

  41. Marin on Monday 7, 2011

    hi jeff, yeah it should run on 5.1

  42. Nyamat on Monday 7, 2011

    hi , well this code is working fine .
    But it is saving on 2 photos in separate folder.Again after running it is saving another two photos , y ?
    Thank you…….

  43. Marin on Monday 7, 2011

    Hi Nyamat, all photos are saved in the camera roll. The albums are just filtered views of the camera roll.

  44. facebook_chuck.brandt on Monday 7, 2011

    This is great! Worked perfectly for my application, a graphic program for iPhone. Could you share the code for how you list the files in this new directory? I need to display a gallery of thumbnails and then show each full screen if tapped.

    Thanks, Chuck Brandt

  45. [...] used my ALAssetsLibrary category to save images to a custom camera roll [...]

  46. [...] You should download the category from my original post here and have a look: http://www.touch-code-magazine.com/ios5-saving-photos-in-custom-photo-album-category-for-download/ [...]

  47. B-Rad on Monday 7, 2011

    Marin,

    Very helpful tutorial but I’ve encountered a problem when attempting to implement the code in a different view controller.

    I’ve created a view controller called “VisitDetail”, imported the AssetsLibrary into the interface, created a *library property and initialized in the implementation file. However, when I attempt to implement the callback and save the image to a custom album, I receive the following error:

    No visible @interface for ‘ALAssetsLibrary’ declares the selector ‘saveImage:toAlbum:withCompletionBlock:’

    I’m using Xcode 4.5.2 and iOS 6 so the “didFinishPickingImage:” method has been deprecated and replaced with “didFinishPickingMediaWithInfo:”.

    Any insights or assistance you might provide would be most appreciated.

    Thanks in advance,

    – B-Rad

  48. Casey on Monday 7, 2011

    Slick little thing, saved me a day of research as well as trial and error. Thanks for contributing!

  49. AR on Monday 7, 2011

    thank you for this. Saved a lot of time.

    Can we delete the pics from the same album?

  50. Juan González on Monday 7, 2011

    Great piece of code, thank you!!

    Ever thought about putting it in github so you can accept pull requests, get help fixing bugs or to add features to it like cocoapods packaging?

  51. Marin on Monday 7, 2011

    hey Juan, actually some guys already did that, have a look here: https://github.com/Kjuly/ALAssetsLibrary-CustomPhotoAlbum

  52. Juan González on Monday 7, 2011

    Great, thanks Marin!

  53. Nikhil on Monday 7, 2011

    My question is related to ALAssetsLibrary. (This category is very useful by the way. My earlier bumbling around had led to an iPhone with 1000 empty albums :)
    When retrieving photos to be displayed as thumbnails, we need to enumerate through the album using one of the block methods right? Do you find that they are taking an incredibly long time for a huge album? Even if you implement paging in your scroll view, and lazy load the pages, the enumeration still seems to take a significant amount of time. Any thoughts on ameliorating this? If this question does not belong in this comment thread then I apologize in advance.

  54. mumthasir on Monday 7, 2011

    wiil it work in simulator?

  55. Valera on Monday 7, 2011

    Hi, Not all photo is saved. couse then we enumerate groups, our custom album is not editable ([group addAsset: asset]; returns NO). So… what we can do with it? somebody give me a good solution. please.

  56. Michael Barrow on Monday 7, 2011

    Very useful! Thanks!!!

  57. Mark Hampton on Monday 7, 2011

    Hi Marin. Will this work with iOS 6 ? Some concerns were raised here: http://stackoverflow.com/questions/10954380/save-photos-to-custom-album-in-iphones-photo-library

    Thanks for sharing.

  58. Marin on Monday 7, 2011

    Mark I haven’t got the time yet to test it thoroughly on iOS6, but it’s on my to-do list :]

  59. Alessandro Chiarotto on Monday 7, 2011

    Hi,
    but if wan to to save the image png format or in jpg without compression?

  60. Marin on Monday 7, 2011

    Have a look at UIImagePNGRepresentation() and UIImageJPEGRepresentation() – these are the functions you would use to create image data.

  61. [...] I am using the category from here to save my image, the code from the [...]

  62. Jeet on Monday 7, 2011

    hey Marin..
    I just want the Custom photo album not permanent photo album…what will i do?

  63. Jeet on Monday 7, 2011

    it is possible to delete Saving photos in custom photo album ?

  64. Adam on Monday 7, 2011

    I was also interested in how to delete photos?

    Also is there a function like this so that you can save videos to albums also?

  65. Scott on Monday 7, 2011

    Is there a way of modifying this so that you can save videos into custom albums?

    Also i was wondering if it is possible to delete photos too.

    Thanks

  66. Daniel on Monday 7, 2011

    Thank you for this tutorial.

    Do you think you could explain how to retrieve a specific image, from a specific album to display?

    Thanks again for your efforts.

  67. Osvaldo on Monday 7, 2011

    How can we save a photo with the overlay itself. I got an overlay when taking a photo, but i would like to save it with the overlay.

    Does anyone know how can i do this.

  68. Sagar on Monday 7, 2011

    Hi Marin,

    Thanks a lot for great piece of code. Can we have something similar so that mp4 files are added to Videos instead of Photos? Really appreciate the help.

    Secondly, I do not see any filename, will it be available if I need to remove the photos or videos?

    Please reply on mail as well.

  69. Sagar on Monday 7, 2011

    I was able to create custom album and also add assets to it.

    I also need to display list of saved files to my custom folder. I am using

    ALAssetRepresentation* representation = [result defaultRepresentation];
    [representation filename];

    But the filename that I get here is IMG_0261.mp4 which is not the the filename of file I had saved. How do I achieve it?

  70. Bob on Monday 7, 2011

    I love the sample app, but when I try to use the files use the ALAssetsLibrary+CustomPhotoAlbum code I get the following Error:

    Apple Mach-O Linker Error
    Linker command failed with exit code 1 (use -v to see invocation)

    Thanks

  71. Lucy on Monday 7, 2011

    GREAT TUTORIAL!!!!!

    But I have the same issue as Sagar, “Is there a way to save the file with a custom name?”

    Thank you,
    Lucy