显示标签为“Storyboard”的博文。显示所有博文
显示标签为“Storyboard”的博文。显示所有博文

2011年12月20日星期二

Using Storyboards To Make Navigation Based iPhone Apps

Using Storyboards To Make Navigation Based iPhone Apps:


Over the past few weeks I’ve been doing a series on using the new storyboard feature in XCode for iOS apps. The short story here is that we can now compose our iOS apps in a completely new way when we are coding apps in iOS 5. Storyboards are not backward compatible.

Today, I’m going to show you how to using storyboards to create a navigation based app, with and without a table view. If you haven’t already done so, be sure to read my previous two posts on storyboards in iOS:


Step One: Create a New Storyboard Based iOS Application


Make sure to have a storyboard app started out (covered in the last post on storyboards). Your app will look something like this:


Step Two: Delete Default Scene


We need the navigation controller to be the first scene in our storyboard, so we’ll need to remove the scene that XCode place here for us. Select the scene right in Interface Builder and hit the delete button. You will be left with an empty storyboard.

Step Three: Add A Navigation Controller


Use the object library to drag a navigation controller unto the storyboard. XCode will insert the navigation controller and make it the first scene on the storyboard for you automatically. You will also get the root view controller automatically setup and connected with a seque already connected.

Step Four: Add A Button To The First Scene


Select the scene with the title Root View Controller. Use the object library to drag a button onto the root view controller. Set the button title to Red. It should look something like this:

Step Five: Connect A New Scene To The Button


Now we want to move to a new scene when users touch the Red button. Drag a new view controller from the object library into the storyboard and change the view controller’s background color to red.

Then control-click the button and drag the blue line to the view controller. Choose Push for the seque type. Your storyboard will look something like this:



That’s all there is to it when setting up navigation. Now, I’m going to be clever and add more than one scene to my navigation project. Here is what my storyboard looks like:



This app will push new color scenes to the navigation controller based on what button the user presses. All with no coding at all yet.

Step Six: Pushing Model Content Across Scenes


Usually, when you are working with apps that support navigation you are following the Model-View-Controller (MVC) design pattern. This means that one view controller will need to pass a reference to the part of the model that will be presented in the next view controller. So, here our root view controller might need to pass something to the detail view controllers that we have set up here.

Before, this was done as part of the IBAction associated with a user control or in the table view delegate method didSelectRow:atIndexPath: . But, now we don’t have any code associated with these transitions. Luckily, we can get references to the storyboard components from within our view controllers.

So, all we need to do to pass on model references during these storyboard transitions is to override one of these two key UIViewController methods:

- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;

To use these method you must make sure that your view controller has a custom code class associated with it. For our example, to set the custom class for our root view controller we can simply use the ViewController that was originally created for us by XCode.

But, we’ll have to set the custom class identity of the view controller on the storyboard to ViewController using Interface Builder.

So, click on the root view controller on the storyboard to select it and then use the Identity Inspector to set the view controller’s custom class to ViewController .



Great, now you can put code into ViewController and it will execute during key events like seque transitions.

In my contrived example, I am going to simply change the view controller’s title property to the text title on the button that the user pressed just to show you how its done:

#import "ViewController.h"

@implementation ViewController

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ UIButton *button = (UIButton *)sender; UIViewController *vc = [segue destinationViewController]; vc.title = button.titleLabel.text; }

@end

Now, when you go from the root view controller to a detail view the title property (in the navigation bar) will change as well. Again, this where you would do something meaningful with your model content.

That’s it for now – keep your eye out for some more storyboard related posts coming out in the near future. Let me know what you think about storyboards in the comments below!

2011年11月16日星期三

iOS5: Saving photos in custom photo album

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
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.
» Marin's homepage    » Contact    » Marin's Cocos2D game creation course