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

Ray Wenderlich
iPhone programming is like a ladybug - fun and only a little scary!

iPhone programming is like a ladybug - fun and only a little scary!

Update 6/02/14: Fully updated for iOS 7 by Jorge Jordán.

The iPhone is an amazing platform to develop on for indie software developers. It’s never been easier to come up with your own unique app idea, code something up, and have it be available to millions of potential customers!

Lately I’ve been getting a lot of questions from people new to iOS development asking how to get started. So I thought it would be helpful to write an iOS tutorial series tailored for beginners.

But rather than focusing in detail on just one topic, you’re going to dive in and create an entire functional app from scratch. By the end, you’ll have tried out many areas of iPhone development, and ready to dig in further.

So what’s the app you’re going to make? Well, there’s a story behind that…

The other night, I saw a picture of a Potato Bug for the first time and started freaking out because it was so big and ugly! Then I got obsessed with looking up all kinds of scary bug pictures online. So to spread the fun, you’re going to make an app for that – rating scary bugs!

While making this app, you’ll learn some of the most commonly used topics in iPhone development:

  • What You Need to Get Started with iPhone Development
  • How to store your app data in a Model
  • How to use Table Views – including adding and deleting rows
  • How to create a detail view for a row
  • How to support both Portrait & Landscape orientations
  • How to use Navigation Controllers
  • How to use an Image Picker
  • How to use common controls such as a text field, button, and image view
  • How to add icons and default images
  • Bonus: How to handle long-running operations

It sounds like a lot, but don’t get scared – you’re not afraid of no bugs!

In this first part of this three-part iOS tutorial series, you’ll learn how to load your model with a list of bugs and display them in a table view. (Jump to Part Two or Part Three)

This iOS tutorial is for beginner iOS developers, however it assumes you are familiar with Objective-C and programming in general. If you are new to Objective-C, I recommend reading Apple’s Objective-C Programming Language Guide first.

What You Need

First things first – to develop for the iPhone, you’ll need a Mac. Pretty much any Mac will do, as long as it’s powerful enough to run the latest version of the Mac OS, Mavericks. But if you’re looking to go the cheap route, you can pick up a Mac Mini for relatively cheap, and it works just fine for a development machine.

Next, you’ll need to get a copy of XCode, Apple’s IDE for iOS development. So if you haven’t already, register for a free account at the iPhone Dev Center and download a copy of Xcode from the Mac App Store.

If you’d like, you can sign up for the paid iPhone Developer Program that allows you to distribute your apps on the App Store, but if you just want to try out iOS development the free account works fine.

If you get serious about iOS development, you’ll probably want physical device(s) (iPhone 4/iPhone 5/iPod Touch/iPad) as well. It’s true that you can do a lot of testing with just the Simulator, but there are some APIs that don’t work on the Simulator, and you’ll need a physical device for performance testing.

That’s it – so if you haven’t already, grab a copy of XCode, fire it up, and continue on!

Hello, Table View!

You’re going to start out by using one of the most common controls on the iPhone – the Table View. You’ve probably seen the Table View in a lot of apps already, here are a few examples:

UITableView Examples

So anyway, your first screen in the app will have one of these, to display a list of scary bugs!

Start by going to File\New Project… in XCode, select the iOS\Application\Master-Detail Application, and click Next.

Creating an app with the master detail application template

On the next page, enter ScaryBugs for the Product Name, enter a unique string for your company identifier (com.yourcompanyname or com.yourname is best), select iPhone on the Devices drop down and enter RWT as Class Prefix. Click Next when you’re done.

Project Settings for scary bugs app

Choose a place to save your project and click Create. And before you do anything else, check out what you’ve got so far! In the main menu choose Product\Destination\iOS Simulator\iPhone Retina (3.5-inch), then click the Run button. If all goes well, you should see the following in your simulator:

The main screen created by the master detail template

You can tap the + button to create a new entry, and then tap the new row to see a detail view for it:

Detail view created by master detail application template

So as you can see, you already have a working project to start from since you chose the Master-Detail Application template.

You’re not going to dig into the template since that’s beyond the scope of this iOS tutorial, but just notice that you have an empty table view and detail view set up and ready to go – you just have to fill it in with data!

So to do that, create a class to keep track of your scary bugs.

A Scary Data Model: Organization

Notice how there’s a hierarchy of folders in the Project Navigator section of XCode:

The project navigator in Xcode

The template comes set up with a root group, and a Supporting Files group. These groups are just for organizational purposes, so feel free to change them however you want. In your case, you’re going to have a fair number of files in this project, so it’s better to organize things a bit.

First, create a new group to store the User Interface files in. To do this, control-click the Scary Bugs group and select New Group. Then control click the new group it created and select rename, and name it GUI. Drag the existing files from the root into the GUI group (but not Supporting Files). It should now look like this:

Organizing Project Navigator tree, part 1

Now create a second new group, and name it Model, because you’re about to add couple classes for your data model there. Your tree should now look like the following:

Creating a group for the model

Before you begin, it’s important for you to know how things are going to be organized on this tutorial:

  1. RWTScaryBugData: Contains bug name and rating.
  2. RWTScaryBugDoc: Contains full size image, thumbnail image, RWTScaryBugData.

The reason you’re setting things up like that is it will make things easier in the follow-up for this iOS tutorial, where you’re going to start saving your data to the disk, implementing file sharing, and the like.

A Scary Data Model: Implementation

Ok so Control-click on the Model group and click New File…. Select the iOS\Cocoa Touch\Objective-C class template, and click Next.

Creating a file with the Objective-C class template

Name the class RWTScaryBugData, enter NSObject for subclass, and click Next.

Creating a class that derives from NSObject in Xcode

In the final popup, click Create again. If all went well, your Project Navigator should now look similar to this:

Project organization, part 3

Ok, time to create your RWTScaryBugData class. Replace RWTScaryBugData.h with the following:

#import <Foundation/Foundation.h>
 
@interface RWTScaryBugData : NSObject
 
@property (strong) NSString *title;
@property (assign) float rating;
 
- (id)initWithTitle:(NSString*)title rating:(float)rating;
 
@end

This is pretty simple stuff – you’re just declaring an object with two properties – a string for the name of the bug, and a float for how scary you rated it. You use two property attributes for these:

  • strong: This specifies that the runtime should automatically keep a strong reference to the object. This is a fancy way of saying that the ARC runtime will keep the object in memory as long as there’s a reference to it around, and deallocate it when no references remain. For more information, check out your Beginning ARC in iOS 5 Tutorial.
  • assign: This means the property is set directly, with no memory management involved. This is what you usually set for primitive (non-object) types like a float.

You also define an initializer for the class, so you can set the title and rating when you create the bug.

Switch over to RWTScaryBugData.m and replace it with the following:

#import "RWTScaryBugData.h"
 
@implementation RWTScaryBugData
 
@synthesize title = _title;
@synthesize rating = _rating;
 
- (id)initWithTitle:(NSString*)title rating:(float)rating {
  if ((self = [super init])) {
    self.title = title;
    self.rating = rating;
  }
  return self;
}
 
@end

Again, extremely simple stuff here. You synthesize your properties, and create your initializer to fill in your instance variables from the passed-in parameters. Note there is no need for dealloc, since you are using ARC.

Ok that’s it for RWTScaryBugData. Now follow the same steps you did above to create another subclass of NSObject, this time named RWTScaryBugDoc.

Replace RWTScaryBugDoc.h with the following:

#import <Foundation/Foundation.h>
 
@class RWTScaryBugData;
 
@interface RWTScaryBugDoc : NSObject
 
@property (strong) RWTScaryBugData *data;
@property (strong) UIImage *thumbImage;
@property (strong) UIImage *fullImage;
 
- (id)initWithTitle:(NSString*)title rating:(float)rating thumbImage:(UIImage *)thumbImage fullImage:(UIImage *)fullImage;
 
@end

Nothing of particular note here – just creating some instance variables/properties and an initializer.

Replace RWTScaryBugDoc.m with the following:

#import "RWTScaryBugDoc.h"
#import "RWTScaryBugData.h"
 
@implementation RWTScaryBugDoc
@synthesize data = _data;
@synthesize thumbImage = _thumbImage;
@synthesize fullImage = _fullImage;
 
- (id)initWithTitle:(NSString*)title rating:(float)rating thumbImage:(UIImage *)thumbImage fullImage:(UIImage *)fullImage {  
  if ((self = [super init])) {
    self.data = [[RWTScaryBugData alloc] initWithTitle:title rating:rating];
    self.thumbImage = thumbImage;
    self.fullImage = fullImage;
  }
  return self;
}
 
@end

And that’s it – your data model is complete! Time to create some sample data and display it in the table view.

A Different Kind of Bug List

First, you’ll set up your table view so it can handle displaying a list of RWTScaryBugDocs. The first thing you have to do is modify your table view so that it returns a dynamic list of rows (rather than a hardcoded single row that the template set up for you).

To do this, open Main.storyboard. This allows you to visually layout the different “screens” in your app. As you can see, the app is currently set up to have a navigation controller (the thing that makes it easy to slide between different screens), with the root controller the master screen, and a secondary controller as the detail screen.

Select the Master View Controller, and in the selection area in the left panel, select the Table View. In the inspector to the right, make sure the Content is set to Dynamic Prototypes.

Setting table view to use dynamic prototype cells

This is what allows you to design a single table view cell the way you like in the Storyboard Editor, and easily create instances of the cell via code. You just want a basic cell, so make sure the cell is using the Basic style.

Select the Table View Cell on the left, and in the Attributes Inspector make sure the Style is set to Basic. Also set the Identifier to MyBasicCell.

Setting cell style and reuse identifier

For more information on creating custom cells, check out your Beginning Storyboards in iOS 5 Tutorial.

OK, now that you have your table view set up correctly visually, you just need to update the code to fill in the table with a list of scary bugs.

You’ll store your RWTScaryBugDocs in a NSMutableArray, the collection class that you use for arrays that should be able to dynamically change in size.

Add the following line to RWTMasterViewController.h, between the @interface and @end lines:

@property (strong) NSMutableArray *bugs;

This will be the instance variable/property that you’ll use to keep track of your list of bugs.

Now go over to RWTMasterViewController.m and make the following changes:

// At top of file
#import "RWTScaryBugDoc.h"
#import "RWTScaryBugData.h"
 
// After @implementation
@synthesize bugs = _bugs;
 
// At the end of viewDidLoad
self.title = @"Scary Bugs";
 
// Replace the return statement in tableView:numberOfRowsInSection with the following:
return _bugs.count;
 
// Replace tableView:cellForRowAtIndexPath with the following
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  UITableViewCell *cell = [tableView
               dequeueReusableCellWithIdentifier:@"MyBasicCell"];
  RWTScaryBugDoc *bug = [self.bugs objectAtIndex:indexPath.row];
  cell.textLabel.text = bug.data.title;
  cell.imageView.image = bug.thumbImage;
  return cell;
}

Ok, finally something interesting to discuss!

First, note that you set a property called title to the string “Scary Bugs.” title is a special built-in property on view controllers. When a Navigation Controller displays a view controller, it shows whatever is in the title property in the title bar. So by setting this, you should see “Scary Bugs” up top!

Next, when constructing a table view with dynamic rows you have to override numberOfSectionsInTableView and numberOfRowsInSection to tell the OS how many sections/rows should be displayed in the table view. You just have 1 section, so you don’t have to do anything because the template is already set up to return 1 section. For the rows, you just return the number of objects in your bugs array.

Finally, you implement tableView:cellForRowAtIndexPath, which is probably the most important method to implement when making a table view. Here, you set up the cell that will be displayed for a particular row. The OS will call this method once per row for each row so you can set it up.

Take a look to this method in detail, since this is particularly important:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  UITableViewCell *cell = [tableView
               dequeueReusableCellWithIdentifier:@"MyBasicCell"];
  RWTScaryBugDoc *bug = [self.bugs objectAtIndex:indexPath.row];
  cell.textLabel.text = bug.data.title;
  cell.imageView.image = bug.thumbImage;
  return cell;
}

The first line calls a helper function called dequeueReusableCellWithIdentifier to try to return a reusable cell. What is this all about?

Well, it’s an important performance optimization. Keep in mind that table views can contain a very large number of rows, but only a certain number of them are displayed on screen at a time. So rather than creating a new cell each time a new row cycles into the screen, the OS can improve performance by re-using a cell that was already created, but scrolled off-screen.

So that’s what the dequeueReusableCellWithIdentifier call is. If there’s not a reusable cell available, you just create a new cell based on the cell you set up in Interface Builder (remember how you set it as basic, and named it MyBasicCell).

In the Storyboard Editor you can customize the layout of the cell, or use one of the built-in ones. In your case, you chose the Basic style, which adds a label and image you can set.

If you’re curious what the different standard table view cell options look like, check out the “Standard Styles for Table-View Cells” section in the Table View Programming Guide.

Finally, you configure the cell by setting its textLabel and imageView (which are available with the Basic style).

Believe it or not that’s all you need to do! Now you just need to set up some sample data for the table view to display.

Scary Bug Pictures!

But of course you’ll need some scary bug pictures for that! You can either browse the Internet and find some, or download these Scary Bug Pictures I found on stock.xchng.

Once you’ve downloaded the files or gotten your own, drag them all into the root of your Project Navigator tree. When the popup appears, make sure Copy items into destination group’s folder (if needed) is checked, and click Finish.

Adding scary bugs files to project

Then open up RWTAppDelegate.m and make the following changes:

// At top of file
#import "RWTMasterViewController.h"
#import "RWTScaryBugDoc.h"
 
// At beginning of application:didFinishLaunchingWithOptions
RWTScaryBugDoc *bug1 = [[RWTScaryBugDoc alloc] initWithTitle:@"Potato Bug" rating:4 thumbImage:[UIImage imageNamed:@"potatoBugThumb.jpg"] fullImage:[UIImage imageNamed:@"potatoBug.jpg"]];
RWTScaryBugDoc *bug2 = [[RWTScaryBugDoc alloc] initWithTitle:@"House Centipede" rating:3 thumbImage:[UIImage imageNamed:@"centipedeThumb.jpg"] fullImage:[UIImage imageNamed:@"centipede.jpg"]];
RWTScaryBugDoc *bug3 = [[RWTScaryBugDoc alloc] initWithTitle:@"Wolf Spider" rating:5 thumbImage:[UIImage imageNamed:@"wolfSpiderThumb.jpg"] fullImage:[UIImage imageNamed:@"wolfSpider.jpg"]];
RWTScaryBugDoc *bug4 = [[RWTScaryBugDoc alloc] initWithTitle:@"Lady Bug" rating:1 thumbImage:[UIImage imageNamed:@"ladybugThumb.jpg"] fullImage:[UIImage imageNamed:@"ladybug.jpg"]];
NSMutableArray *bugs = [NSMutableArray arrayWithObjects:bug1, bug2, bug3, bug4, nil];
 
UINavigationController *navController = (UINavigationController *) self.window.rootViewController;
RWTMasterViewController *masterController = [navController.viewControllers objectAtIndex:0];
masterController.bugs = bugs;

Here you just use the RWTScaryBugDoc initializer to create four sample bugs, passing in the title, rating, and images for each. You add them all to a NSMutableArray, and set them on your table view.

Speaking of which, you can get a pointer to the RootViewController since you know it’s the first view controller in the navigation controller’s stack. There are other ways you could have gotten a pointer as well, but this is one easy way.

And that’s it! Compile and Run your app, and if all works well, you should see a list of (mostly) frightening bugs in your table view!

Scary Bugs Table View

Where To Go From Here?

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

Please let me know if anything in the above is confusing or if you’d like me to go into more detail about anything.

Next in the iOS tutorial series, you’ll learn how to create a detail view for the bugs so you can edit and rate your bugs!

Ray Wenderlich

Ray is an indie software developer currently focusing on iPhone and iPad development, and the administrator of this site. He’s the founder of a small iPhone development studio called Razeware, and is passionate both about making apps and teaching others the techniques to make them.

When Ray’s not programming, he’s probably playing video games, role playing games, or board games.

User Comments

177 Comments

[ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 ]
  • I'm confused. In RWTScaryBugData.m in the initWithTitle: method the instance variables are being initialized as self.title = title and self.rating = rating.

    However, in "Programming with Objective-C" guide by Apple (https://developer.apple.com/library/mac ... ctiveC.pdf) on page 48, it spells out that:

    "You should always access the instance variables directly from within an initialization method because at the time a property is set, the rest of the object may not yet be completely initialized. Even if you dont provide custom accessor methods or know of any side effects from within your own class, a future subclass may very well override the behavior."

    So I assume it means the variables should've been inited as:
    _title = title
    _rating = rating.
    pentool
  • I am a 15 year IT Pro with the itch to learn something new. IOS development sounded like a fun area to get into. I searched the web and came across the ScaryBugs tutorial and decided to run with it. So I got to this portion:

    "Choose a place to save your project and click Create. And before you do anything else, check out what youve got so far! In the main menu choose Product\Destination\iOS Simulator\iPhone Retina (3.5-inch), then click the Run button. If all goes well, you should see the following in your simulator:"

    I followed these directions and all did not go well. I keep getting build errors about:

    "No provisioning profiles with a valid signing identity (i.e. certificate and private key pair) were found."

    My build settings are all set to my name. I was able to figure out how to create certificates for myself which cleared the initial error. I also tried all set to "Don't sign" which didn't help any. For this one, I have been all over the internet looking for a solution to this issue without much luck. Can someone please help me out here?

    Mac OS X Mountain Lion 10.8.5
    XCode 5.1

    Thanks a bunch!!
    ImJustAFriend
    ImJustAFriend
  • HELLO THERE!

    I am new at this and I am trying my best to learn iPhone programming due to demanding Mobile Applications class. My bug does not appear. I try to put the images everywhere but nowhere is good enough. Can you point me in the right direction? I put in the root, in the scary bugs folder, in the support files folder, and the other folders but the bugs will never appear.

    BTW you side is awesome!

    Thanks.
    it.specialist
  • very helpful and awesome tutorial...
    dheerajk809
  • http://androidfreakers.com
    hiessu wrote:I've just check your reply about _variable vs. variable. Maybe it's personal choice. :)
    dheerajk809
  • Amazing guide for those hoping to develop IOS based apps and software.

    Much better than Lynda.com, won't be sending people there anymore and i have great influence over where 100s of people go each year to learn how to develop stuff.

    Keep up the good work

    -God
    d'godreidy
  • I definitely appreciate the tutorial. I understand you guys put a lot of work into it. I have some corrective criticisms however. I suggest you have someone at your location to try out your tutorial and make sure they actually work.

    I'm getting in error here:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    UITableViewCell *cell = [tableView
    dequeueReusableCellWithIdentifier:@"MyBasicCell"];
    RWTScaryBugDoc *bug = [self.bugs objectAtIndex:indexPath.row];
    cell.textLabel.text = bug.data.title;
    cell.imageView.image = bug.thumbImage;
    return cell;
    }

    2014-06-12 22:26:28.228 ScaryBugs[1955:60b] *** Assertion failure in -[UITableView _configureCellForDisplay:forIndexPath:], /SourceCache/UIKit/UIKit-2935.137/UITableView.m:6509
    2014-06-12 22:26:28.231 ScaryBugs[1955:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
    *** First throw call stack:
    (0x2e512f0b 0x38ca9ce7 0x2e512ddd 0x2eebfe2f 0x30e765b1 0x30d540d5 0x30e76421 0x30e751b1 0x30e1c3fb 0x30e1bc51 0x30d42305 0x309be31b 0x309b9b3f 0x309e8b4d 0x30dbe89f 0x30dbcea9 0x30dbc0e7 0x30dbc06f 0x30dbc007 0x30db4681 0x30d48697 0x30dbbd59 0x30dbb829 0x30d4d615 0x30d4add9 0x30db4a51 0x30db16e5 0x30dabcc9 0x30d47c97 0x30d46df9 0x30dab405 0x333b4b55 0x333b473f 0x2e4dd847 0x2e4dd7e3 0x2e4dbfaf 0x2e446769 0x2e44654b 0x30daa62b 0x30da5891 0xcd49 0x391a7ab7)
    libc++abi.dylib: terminating with uncaught exception of type NSException

    I followed your tutorial exactly. I have no idea why. I'll go thru it again I guess but I followed it word for word.
    Pragmatous
  • Extremely helpful tutorial and I am really very impressed with the given article with the screenshots for easy learning.
    satvikpatel
  • Hi,

    Great tutorial. But more fine grained details could have been more useful.
    However I was getting following crash after copy almost everything from this tutorial
    "reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'"

    I guess "UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyBasicCell"]; was returning nil to me. I have fixed the issue changing MyBasicCell to Cell. I got the fix from stackoverflow.

    Could you also fix it.

    Thanks
    Tej
    tej
  • I'm new with programming in general and with Obj-C. I followed the tutorial well. But I have two questions.

    1. Technically, why is the array data in AppDelegate.m? If your app had more tables, would their arrays be detailed in the AppDelegate.m file, too? Could the array data go in the MasterViewController.m file?

    2. If I wanted to place my array data in a plist file, what code would I use to link the plist to the table and build the table using the plist's data? And where would that code go--in the AppDelegate.m file or in the MasterViewController.m file or somewhere else?

    Thanks!
    Carta
  • God bless u Ray. Amazing tutorials!
    mpred
  • I got an error, I checked everything it took me 1 hour I even copied exactly everything that is in the finished project.

    The problem is that the cell doesn't configure.
    I set the identifier and made it dynamic.
    I checked everything. Your sample code does work but mine doesn't work even if i copy everything yours has .


    Here is the error, please let me know what it could be.



    2014-09-20 14:07:25.953 ScaryBugs[4043:60b] *** Assertion failure in -[UITableView _configureCellForDisplay:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2935.137/UITableView.m:6509
    2014-09-20 14:07:25.957 ScaryBugs[4043:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
    *** First throw call stack:
    (
    0 CoreFoundation 0x017f01e4 __exceptionPreprocess + 180
    1 libobjc.A.dylib 0x0156f8e5 objc_exception_throw + 44
    2 CoreFoundation 0x017f0048 +[NSException raise:format:arguments:] + 136
    3 Foundation 0x0114f4de -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
    4 UIKit 0x00320d7f __53-[UITableView _configureCellForDisplay:forIndexPath:]_block_invoke + 426
    5 UIKit 0x0029581f +[UIView(Animation) performWithoutAnimation:] + 82
    6 UIKit 0x00295868 +[UIView(Animation) _performWithoutAnimation:] + 40
    7 UIKit 0x00320bd0 -[UITableView _configureCellForDisplay:forIndexPath:] + 108
    8 UIKit 0x0032813d -[UITableView _createPreparedCellForGlobalRow:withIndexPath:] + 442
    9 UIKit 0x003281f3 -[UITableView _createPreparedCellForGlobalRow:] + 69
    10 UIKit 0x00309ece -[UITableView _updateVisibleCellsNow:] + 2428
    11 UIKit 0x0031e6a5 -[UITableView layoutSubviews] + 213
    12 UIKit 0x0029e964 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
    13 libobjc.A.dylib 0x0158182b -[NSObject performSelector:withObject:] + 70
    14 QuartzCore 0x03c5b45a -[CALayer layoutSublayers] + 148
    15 QuartzCore 0x03c4f244 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
    16 QuartzCore 0x03c5b3a5 -[CALayer layoutIfNeeded] + 160
    17 UIKit 0x00360ae3 -[UIViewController window:setupWithInterfaceOrientation:] + 304
    18 UIKit 0x00276aa7 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 5212
    19 UIKit 0x00275646 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 82
    20 UIKit 0x00275518 -[UIWindow _setRotatableViewOrientation:updateStatusBar:duration:force:] + 117
    21 UIKit 0x002755a0 -[UIWindow _setRotatableViewOrientation:duration:force:] + 67
    22 UIKit 0x0027463a __57-[UIWindow _updateToInterfaceOrientation:duration:force:]_block_invoke + 120
    23 UIKit 0x0027459c -[UIWindow _updateToInterfaceOrientation:duration:force:] + 400
    24 UIKit 0x002752f3 -[UIWindow setAutorotates:forceUpdateInterfaceOrientation:] + 870
    25 UIKit 0x002788e6 -[UIWindow setDelegate:] + 449
    26 UIKit 0x00352b77 -[UIViewController _tryBecomeRootViewControllerInWindow:] + 180
    27 UIKit 0x0026e474 -[UIWindow addRootViewControllerViewIfPossible] + 591
    28 UIKit 0x0026e5ef -[UIWindow _setHidden:forced:] + 312
    29 UIKit 0x0026e86b -[UIWindow _orderFrontWithoutMakingKey] + 49
    30 UIKit 0x002793c8 -[UIWindow makeKeyAndVisible] + 65
    31 UIKit 0x00229bc0 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 2097
    32 UIKit 0x0022e667 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 824
    33 UIKit 0x00242f92 -[UIApplication handleEvent:withNewEvent:] + 3517
    34 UIKit 0x00243555 -[UIApplication sendEvent:] + 85
    35 UIKit 0x00230250 _UIApplicationHandleEvent + 683
    36 GraphicsServices 0x037e5f02 _PurpleEventCallback + 776
    37 GraphicsServices 0x037e5a0d PurpleEventCallback + 46
    38 CoreFoundation 0x0176bca5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
    39 CoreFoundation 0x0176b9db __CFRunLoopDoSource1 + 523
    40 CoreFoundation 0x0179668c __CFRunLoopRun + 2156
    41 CoreFoundation 0x017959d3 CFRunLoopRunSpecific + 467
    42 CoreFoundation 0x017957eb CFRunLoopRunInMode + 123
    43 UIKit 0x0022dd9c -[UIApplication _run] + 840
    44 UIKit 0x0022ff9b UIApplicationMain + 1225
    45 ScaryBugs 0x000033fd main + 141
    46 libdyld.dylib 0x01e37701 start + 1
    )
    libc++abi.dylib: terminating with uncaught exception of type NSException
    ivanlares
[ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 ]

Other Items of Interest

Ray's Monthly Newsletter

Sign up to receive a monthly newsletter with my favorite dev links, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Vote for Our Next Tutorial!

Every week, we alternate between Gaming and Non-Gaming tutorial votes. This week: Non-Gaming!

    Loading ... Loading ...

Last week's winner: How to Make a Simple 2D Game with Metal.

Suggest a Tutorial - Past Results

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in October: Xcode 6 Tips and Tricks!

Sign Up - October

Our Books

Our Team

Tutorial Team

  • Kyle Richter
  • Dani Arnaout
  • Dominik Hauser

... 52 total!

Update Team

  • Zouhair Mahieddine
  • Ray Fix

... 14 total!

Editorial Team

  • Alexis Gallagher

... 22 total!

Code Team

  • Orta Therox

... 3 total!

Subject Matter Experts

... 4 total!