iOS Tutorial: How To Create A Simple iPhone App Tutorial: Part 3/3

An iOS tutorial for complete beginners that shows you how to make your first iPhone app, from scratch! By Ray Wenderlich.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 2 of this article. Click here to view the first page.

Contents

Hide contents

Bonus: Handling Long-Running Operations

If you run the app on the Simulator, everything probably appears fine, but if you run it on your iPhone and go to tap a picture to change it, there is a long delay as the UIImagePicker initializes. After picking a picture, there is another long delay as the image is resized (especially if it’s large). This is a very bad thing, as it makes your application seem unresponsive to users.

The main rule to keep in mind is that you should never perform long-running operations on the main thread. You’re currently violating this rule in two places, which is why your app appears unresponsive.

What you should do instead is run long-running operations on a background thread. Ideally, the operation would be done in the background as the user continues to do other things. But if the work is required to occur before the user can continue (such as loading the image picker), at the very least you should display a loading indicator of some sort so the user understands that the app is working and not just broken.

So that’s what you’ll do here – run the long-running code on a background thread, and display a loading view on the foreground thread while you wait for the operation to complete.

The desire to display a loading view is a common problem for app developers, so a lot of people have created some activity indicator libraries that you can use to save yourself some time doing it yourself. I’ve tried a bunch of these, my current favorite is SVProgressHUD by Sam Vermette, so try that. You can download a copy off the SVProgressHUD Github page.

Once you’ve downloaded SVProgressHUD, add SVProgressHUD.h and SVProgressHUD.m to your project under the Views group. You also have to perform two configuration steps:

  1. Add required library. Click your project in the Project Navigator and select your ScaryBugs target. Select the Build Phases tab and expand the Link Binary With Libraries section. Click the + button and add QuartzCore.framework.

Adding required QuartzCore.framework library in Xcode

At this point you should be able to build your project without errors.

Then make the following changes to RWTDetailViewController.m:

// At top of file
#import "SVProgressHUD.h"

// Replace addPictureTapped with the following:
- (IBAction)addPictureTapped:(id)sender {
    if (self.picker == nil) {
        
        // 1) Show status
        [SVProgressHUD showWithStatus:@"Loading picker..."];
        
        // 2) Get a concurrent queue form the system
        dispatch_queue_t concurrentQueue =
        dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        // 3) Load picker in background
        dispatch_async(concurrentQueue, ^{
            
            self.picker = [[UIImagePickerController alloc] init];
            self.picker.delegate = self;
            self.picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
            self.picker.allowsEditing = NO;
            
            // 4) Present picker in main thread
            dispatch_async(dispatch_get_main_queue(), ^{
                [self presentViewController:_picker animated:YES completion:nil];
                [SVProgressHUD dismiss];
            });
            
        });
        
    }  else {
        [self presentViewController:_picker animated:YES completion:nil];
    }
}

There’s a lot of new ideas here, so you’ll go over this section by section.

  1. Here you use the SVProgressHUD helper class you just added to show a “Loading” GUI with a spinner on the screen. This way the user knows some work is going on and that the app hasn’t just locked up.
  2. You want to load the image picker in the background. You can do this on iOS with a technology called Grand Central Dispatch. You won’t go over it in huge detail here (but if you are curious, read this iOS tutorial). For now, all you need to know is this line gives you a queue that you can use to run blocks of code in the background.
  3. This line executes a block of code to load the image picker in the background. If you are confused about the syntax of blocks, check out this iOS tutorial.
  4. Finally, you present the picker on the main queue. Note you must always update the GUI on the main queue – you can’t do it on a background thread.

Similarly, you can perform the image resizing in the background as well. Replace imagePickerController:didFinishPickingMediaWithInfo with this:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    
    UIImage *fullImage = (UIImage *) [info objectForKey:UIImagePickerControllerOriginalImage];
    
    // 1) Show status
    [SVProgressHUD showWithStatus:@"Resizing image..."];
    
    // 2) Get a concurrent queue form the system
    dispatch_queue_t concurrentQueue =
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 3) Resize image in background
    dispatch_async(concurrentQueue, ^{
        
        UIImage *thumbImage = [fullImage imageByScalingAndCroppingForSize:CGSizeMake(44, 44)];
        
        // 4) Present image in main thread
        dispatch_async(dispatch_get_main_queue(), ^{
            self.detailItem.fullImage = fullImage;
            self.detailItem.thumbImage = thumbImage;
            self.imageView.image = fullImage;
            [SVProgressHUD dismiss];
        });
        
    });
    
    [self dismissViewControllerAnimated:YES completion:nil];

}

And that’s it! Give it a run on your device, and you’ll see a new animation while the long-running work takes place, which makes for a much nicer user experience.

Using SVProgressHUD

Where To Go From Here?

Here is a sample project with all of the code you’ve developed in this iOS tutorial series.

Congratulations – you have finished creating a simple Master/Detail app for iOS! You have dived through a crash course of putting an app together, and can dig into further areas of interest.

Here’s what I’d recommend you read next:

  • The iOS Apprentice: iOS Tutorial Team member Matthijs Hollemans has written a detailed iOS tutorial series on iOS development for beginners that covers everything you need to know to get started with iOS, from the ground up. You can get part one for free by signing up for your monthly iOS newsletter, or you can purchase the whole series in the raywenderlich.com store.
  • Beginning Storyboards in iOS 5 Tutorial: To layout your user interface in iOS 5, you will typically use the Storyboard editor, so it is very important to learn how it works.
  • Beginning ARC in iOS 5 Tutorial: It’s also important to understand how memory management is handled in iOS 5 (and how easy it is with ARC!)
  • How To Use Blocks in iOS 5 Tutorial: If you’re new to blocks, you should check this iOS tutorial out. It also gives some good additional practice with Storyboards.
  • Multithreading and Grand Central Dispatch on iOS: It’s also important to learn how to run tasks in the background to keep your app responsive. This iOS tutorial touched on it, but read this for more details.
  • How To Submit Your App to the App Store: And of course when you finish your app, you’ll want to know how to get it onto the App Store! Read this iOS tutorial for a step-by-step guide.
  • And much more! You have tons of tutorials on iOS on this site. Click this link to see your entire list!

I wish you best of luck in your iOS adventures, and I hope you enjoyed making this ScaryBugs app! If you have any questions or comments, please join the form discussion below!