Touch Code Magazine

Posts about Swift, Apple, iOS, conferences, and more

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:

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:

and a property to keep hold of the assets library:

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

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

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:

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:

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:

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:

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

Tagged under: , , , , ,

Pin it

Marin Todorov is an independent iOS consultant and publisher with complimentary background in server and desktop development. He started developing on an Apple ][ more than 20 years ago and keeps rocking till today. Meanwhile he has worked in great companies like Monster Technologies and Native Instruments, has lived in 4 different countries, and (more recently) is one the founding memebers of the raywenderlich.com tutorial team. Besides crafting code, Marin also enjoys bloging, writing books, teaching and training others, and speaking at mobile conferences. He sometimes open sources his code. He walked the way to Santiago.

Website: http://www.touch-code-magazine.com

77 Comments

  1. Lector

    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. Pingback: Fun Photo Booth released – features iCloud, new Twitter UI, custom photo album (iOS5)

  3. Antonio

    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

    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

    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

    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

    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

    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

    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

    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

    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. pawan Kumar

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

  13. Christian

    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.

  14. RW

    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

  15. RW

    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.

  16. Marin

    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

  17. Bogdan

    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;

  18. Marin

    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

  19. gerald

    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?

  20. Paul

    Hi Marin!

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

  21. Ondrej

    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 :(

  22. Arun

    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 ….

  23. Mithun Dhali

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

  24. Pingback: It’s possible to save image to app’s own photo album without duplicate in Camera Roll?

  25. Chris O

    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.

  26. Andrew

    @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.

  27. Marin

    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

  28. myr0

    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

  29. neeraj

    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

  30. Jaminyah

    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.

  31. Rajneesh

    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.

  32. Marin

    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.

  33. northtree

    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.

  34. Jeff

    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?

  35. Nyamat

    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…….

  36. facebook_chuck.brandt

    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

  37. Pingback: “Free Wallpaper a Day” is live on the AppStore – Part 1/3

  38. Pingback: “Free Wallpaper a Day” is live on the AppStore – Part 2/3 – “The code libraries”

  39. B-Rad

    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

  40. Juan González

    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?

  41. Marin

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

  42. Pingback: iphone开发资源汇总 « T客网 ︱ Techpot

  43. Nikhil

    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.

  44. Valera

    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.

  45. Mark Hampton

    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.

  46. Marin

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

  47. Pingback: UIImage RBG Values Change when Saved to Device Library | BlogoSfera

  48. Jeet

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

  49. Adam

    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?

  50. Scott

    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

  51. Daniel

    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.

  52. Osvaldo

    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.

  53. Sagar

    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.

  54. Sagar

    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?

  55. Bob

    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

  56. Pingback: 常用的几个提高iOS开发效率的开源类库及工具 _ 多看 – Hank的备忘录,关注互联网技术和创业

  57. Lucy

    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

  58. Pingback: IOS 自定义相册 | segment-解决方案

  59. Mithun

    The photos are getting saved as multiple copies into the custom album as well as My PhotoStream and camera roll.That means 3 images are getting created each time i try to save a picture :(

  60. Eric

    for video saving support, just add this function to the category:

    -(void)saveVideoLocalUrl:(NSURL*)assetURL toAlbum:(NSString*)albumName withCompletionBlock:(SaveImageCompletion)completionBlock
    {
    //add the asset to the custom photo album
    [self writeVideoAtPathToSavedPhotosAlbum:assetURL completionBlock:^(NSURL *assetURL, NSError *error) {
    NSLog(@”error: %@”, [error description]);

    [self addAssetURL: assetURL
    toAlbum:albumName
    withCompletionBlock:completionBlock];
    }];
    }

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Back to top