markjnet

iPhone Memory Debugging with NSZombie and Instruments

When your iPhone app crashes with ‘BAD ACCESS’ you’re in trouble – a memory bug where you tried to call a method on a object that was already deleted. Instruments has support for NSZombie – a feature that makes it easy to find the source of the bug by showing you a full history of every alloc, retain, release, and autorelease of the object that caused the crash! Wow. Here’s how:

Basic steps are:

  1. Run in Performance tool ‘Object Allocations’
  2. Stop running and set options on ObjAllocations instrument: ‘Enable NSZombie’ Detection and ‘Record Reference Counts’
  3. Re-run from instruments, when it crashes, click the arrow in the popup zombie dialog
  4. Open up the stack trace view and see the full memory history of the problem object
  5. Wow, how awesome is that?
  6. If you love this post, do me a favor and check out our Free app Focus for Facebook
  7. You might also like my memory management tutorial and other posts under ‘App Development’.

Enable Zombies in Instruments

Enable Zombies in Instruments

Here’s a link to the demo program: ZombieDebug Demo Project. The code we’re looking at in the video is:

@implementation ZombieDebugViewController
 
@synthesize objArray;
 
-(void)rewriteText {
NSMutableString* s = [NSMutableString stringWithCapacity:100];
for (id obj in objArray) {
[s appendFormat:@"%@,\n",obj];
[obj release];
}
label.text = s;
}
 
- (void)viewDidLoad {
[super viewDidLoad];
self.objArray = [NSMutableArray arrayWithCapacity:10];
[objArray addObject:@"I'm a string object"];
[self rewriteText];
}
 
-(IBAction) tapButton:(id)button {
NSNumber* n = [NSNumber numberWithLong:random()];
[objArray addObject:n];
[self rewriteText];
}
 
-(void)dealloc {
[super dealloc];
self.objArray=nil;
}
 
@end

[Slashdot] [Digg] [del.icio.us] [StumbleUpon]

Debugging Tip – objc_exception_throw breakpoint

If an exception is thrown when debugging an iPhone app, without your own exception handling code, that exception won’t stop the debugger until the call stack has totally unwound. On that journey through the call stack it gets caught and disguarded in the event loop. That’s a bummer because then the debugger can’t show you where original exception was raised. This problem is easy to fix by adding a symbolic breakpoint for the runtime’s objc_exception_throw function, which is called as soon as the exception occurs. Here’s how:

1) Run the app in the debugger. There’s an exception we can see in the debugger console:

screen 2

2) Open the debugger from XCode menu Run->Debugger. The stack we can see where the debugger paused is the useless stack where the event loop code caught the exception and then bombed out with its own exception.

screen 4

3) From XCode menu Run->Manage Breakpoints -> Add symbolic breakpoint we add ‘objc_exception_throw’

screen 12

4) Now when we debug run again, the debugger stops as soon as the oringinal exception was thrown, we can see exactly where, and we can poke around an inspect variables etc.

screen 11

[Slashdot] [Digg] [del.icio.us] [StumbleUpon]

Memory Management Basics Tutorial Video

This article is a screen cast video of my tutorial for beginner iPhone programmers, it’s about the basics of memory management in Objective-C. Memory management is a tough nut for the beginner to crack, particularly in Objective-C and Cocoa for iPhone. Check out my iPhone memory management reading list for more voices on memory management.

The tutorial covers: Objective-C object retain counts; using retain, release, and autorelease; explains the autorelease pool in detail and how it works with the event loop; rule of thumb for if an object is in the autorelase pool.



Part 1: retain counts



Part 2: auto-release pool and the event loop



Part 3: auto-release pool and the event loop with retain



Part 4: auto-release pool wrap up



Part 5: properties, dealloc, bugs, auto-release rule of thumb

Thanks for watching!

[Slashdot] [Digg] [del.icio.us] [StumbleUpon]

iPhone Memory Management Reading List

Memory Management in Objective-C for the iPhone gets a lot of beginners confused. It’s a topic that can be explained several different ways, so keep reading and experimenting till it clicks for you. Here’s a list of places to learn about it:

My video lessons: Basics of iPhone Memory Management.

Books

Online

[Slashdot] [Digg] [del.icio.us] [StumbleUpon]

Fixing Blurry Subviews

The app I’m currently working on uses a small panel with extra info in a small font drawn over the top of an image. It’s implemented of course as a UIView nested as the subview in another UIView. My code loads the info panel view from a separate xib file and positions it in the main view with some code like this:

	NSArray *nibContent = [[NSBundle mainBundle] loadNibNamed:@"Box"
                                                     owner:self options:NULL];
	UIView* overlayBox1 = [nibContent objectAtIndex:0];
	[worksheet addSubview:overlayBox1];
	overlayBox1.center = worksheet.center;
	overlayBox1.frame = CGRectOffset(overlayBox1.frame, 0, -140);

It didn’t quite work though, because the detail view came out really blurry. It didn’t look blurry in Interface Builder, but both on the simulator and the iPhone it looked terrible, see below. I spent hours changing font properties and colors, thinking it was some weird text anti-aliasing gone wrong, but it always came out blurry. Can you guess the problem? It’s one of those things that will probably stump you until you’ve run across it yourself…

blurryview1

The problem is Core Graphics awesome power and screen co-ordinates that are floats, not integers. Core Graphics lets you compose your views from graphics not to 100% scale, it will scale everything for you, and it can even position views with sub-pixel accuracy, rendering ‘between’ each pixel with an anti-alias like effect. This is possible because view coordinates are specified with CGRect, which uses CGPoint, where x and y are floats, not ints.

The problem occurs when you have views that are supposed to be drawn normally, ie at 100% scale and at exact pixels. In the code snippet above the subview overlayBox1 is being positioned using its center. Center is a convenience method implemented as a property, it is really setting the frame origin. As the box is sized with an even number of pixels, 174 x 82, setting the origin relative to the center results in an origin at half pixels: 73.5, 69.5. Core Graphics goes ahead and renders at the half pixel position, but as the view is drawn at 100% it means every pixel in the view lies at half pixels on the screen, so each pixel is smeared between 4 neighboring pixels resulting in a big blur.

This is easily fixed, by positioning the view to whole pixels:

	overlayBox2.center = worksheet.center;
	CGRect overlay2Frame = overlayBox2.frame;
	overlay2Frame.origin.x = round(overlay2Frame.origin.x);
	overlay2Frame.origin.y = round(overlay2Frame.origin.y);
	overlayBox2.frame = overlay2Frame;

If you want to play around with this you can download the full example: blurryview.zip

#import "BlurryViewViewController.h"
 
@implementation BlurryViewViewController
 
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        // Custom initialization
    }
    return self;
}
 
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
	[super viewDidLoad];
 
	NSArray *nibContent = [[NSBundle mainBundle] loadNibNamed:@"Box" owner:self options:NULL];
	UIView* overlayBox1 = [nibContent objectAtIndex:0];
	[worksheet addSubview:overlayBox1];
	overlayBox1.center = worksheet.center; //WARNING! blur ahead.
	overlayBox1.frame = CGRectOffset(overlayBox1.frame, 0, -140);
 
	nibContent = [[NSBundle mainBundle] loadNibNamed:@"Box" owner:self options:NULL];
	UIView* overlayBox2 = [nibContent objectAtIndex:0];
	[worksheet addSubview:overlayBox2];
	overlayBox2.center = worksheet.center;
	CGRect overlay2Frame = overlayBox2.frame;
	overlay2Frame.origin.x = round(overlay2Frame.origin.x);
	overlay2Frame.origin.y = round(overlay2Frame.origin.y);
	overlayBox2.frame = overlay2Frame;
 
	NSLog(@"Worksheet1 origin: %f,%f",overlayBox1.frame.origin.x,overlayBox1.frame.origin.y);
}
 
- (void)didReceiveMemoryWarning {
	// Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
 
	// Release any cached data, images, etc that aren't in use.
}
 
- (void)viewDidUnload {
	// Release any retained subviews of the main view.
	// e.g. self.myOutlet = nil;
}
 
- (void)dealloc {
    [super dealloc];
}
 
@end

[Slashdot] [Digg] [del.icio.us] [StumbleUpon]

Ad Hoc Distribution to Windows and Mac – zipping the build

There’s a handy distribution tool for iPhone developers doing beta testing called ‘ad hoc distribution’. With ad hoc distribution a developer can make a special build of an iPhone app that can be installed on testers iPhones and iPods before the app hits the app store. It’s tricky to get working and your testers have to do a bit of work too, but it’s worth the effort. Developers: just keep trying to follow Apple’s instructions until you get it to work on your own device.

When you send the app out to testers, they need to drag and drop it into iTunes to get it on their phone, and this can easily go wrong for Windows users. In OS X when you compress your ad hoc build, you just do this right?

screen-12

On OS X that creates a zip file that includes a resource fork, which is extra stuff that’s not needed in this case. When the zip arrives on your tester’s windows laptop that Mac resource fork just looks like a normal folder to Windows, and it can prevent iTunes on Windows from recognizing the folder as an app… leaving your windows tester baffled as to why they can’t just drag and drop the file into iTunes as you instructed them to.

If they unzip with a windows right click->uncompress file they get this:

cm-capture-11

And you tell your users to drag and drop CallingCard1.app into iTunes, but look inside that folder:

cm-capture-3

__MACOSX is the resource fork thing, and it’s going to confuse poor iTunes on Windows so iTunes ignores the drag and drop, and your testers won’t be able to install. Your testers need the app folder inside the app folder. Confusing! If they unzip with WinZip they are in more luck, because it unzips the content to the current folder and gives them the right app folder right away.

You can save all this trouble though, but making a zip archive in the first place that doesn’t have the Mac resource fork.  BetterZip is a handy Mac app that will do this for you. That preferences setting ‘Remove Mac specific stuff from archives’ keeps __MACOSX out of the zip, and the resulting zip will install on Mac and Windows. Another way to do this is to unzip in windows yourself, find the correct app folder, and re-zip.

screen-2

You can do the re-zip method in windows running in Parallels on your Mac, but it can go horribly wrong. A typical Parallels setup shares the OS X desktop folder as the Windows desktop folder so that your Windows and Mac desktops are one and the same. If you unzip and re-zip in Windows on a shared Mac desktop, then the zip archive will still be messed up. So if you are doing this, do everything in a normal (in the parallels virtual drive) Windows folder.

Finally, good luck, ad-hoc is super tricky.

[Slashdot] [Digg] [del.icio.us] [StumbleUpon]

What Color is My Pixel? Image based color picker on iPhone

Color PickerMy Postcards app has a design screen where you can change colors of things, so I needed a color picker. A very easy way to make a color picker on just about any platform is to make some kind of color pallet image file, display it for the user to click on, and do a call like: getPixelColorAtScreenLocation(x,y)

This was available back in 1983 on my ZX-Spectrum, but alas Cocoa Touch doesn’t have it. (If I missed something I hope a reader will set me straight.) What are some alternatives then?

  • Ditch the color pallet and use sliders to mix colors. Not very user friendly for the everyday user.
  • Manually build a lookup table for position to color. Hard work and what if I want to use a different image?
  • Parse the image file myself and find the color at x,y using some third party library. Maybe…
  • Bend core graphics to my will and have it ‘parse’ the image file for me and make the uncompressed pixels available.

Googling around turned up a way to make the last technique work, which is good because we’re using existing APIs, and it will work for any image:

  1. Make an off screen bitmap image context that is uncompressed and has a known byte to pixel mapping.
  2. Re-draw the color picker image into that context.
  3. Turn x,y touch co-ordinates into a position in the context’s bitmap buffer.
  4. Turn the pixel bytes at the offset position into a UIColor.

I’ve wrapped this up in ColorPickerImageView, a subclass of UIImageView.  When you tap it, it uses this approach to get the pixel color you tapped.  You can also register a simple delegate with it to get a callback with the picked color. You put your own image in it, so you can make it a little color pallet in a corner or make it fill the screen. As it’s derived from UIImageView, you use it just like UIImageView in code or in Interface Builder. The  pixel grabbing source code is below, and the whole class is included in: ColorPicker code to download and copy.

- (UIColor*) getPixelColorAtLocation:(CGPoint)point {
	UIColor* color = nil;
	CGImageRef inImage = self.image.CGImage;
	// Create off screen bitmap context to draw the image into. Format ARGB is 4 bytes for each pixel: Alpa, Red, Green, Blue
	CGContextRef cgctx = [self createARGBBitmapContextFromImage:inImage];
	if (cgctx == NULL) { return nil; /* error */ }
 
    size_t w = CGImageGetWidth(inImage);
	size_t h = CGImageGetHeight(inImage);
	CGRect rect = {{0,0},{w,h}}; 
 
	// Draw the image to the bitmap context. Once we draw, the memory
	// allocated for the context for rendering will then contain the
	// raw image data in the specified color space.
	CGContextDrawImage(cgctx, rect, inImage); 
 
	// Now we can get a pointer to the image data associated with the bitmap
	// context.
	unsigned char* data = CGBitmapContextGetData (cgctx);
	if (data != NULL) {
		//offset locates the pixel in the data from x,y.
		//4 for 4 bytes of data per pixel, w is width of one row of data.
		int offset = 4*((w*round(point.y))+round(point.x));
		int alpha =  data[offset];
		int red = data[offset+1];
		int green = data[offset+2];
		int blue = data[offset+3];
		NSLog(@"offset: %i colors: RGB A %i %i %i  %i",offset,red,green,blue,alpha);
		color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)];
	}
 
	// When finished, release the context
	CGContextRelease(cgctx);
	// Free image data memory for the context
	if (data) { free(data); }
 
	return color;
}
 
- (CGContextRef) createARGBBitmapContextFromImage:(CGImageRef) inImage {
 
	CGContextRef    context = NULL;
	CGColorSpaceRef colorSpace;
	void *          bitmapData;
	int             bitmapByteCount;
	int             bitmapBytesPerRow;
 
	// Get image width, height. We'll use the entire image.
	size_t pixelsWide = CGImageGetWidth(inImage);
	size_t pixelsHigh = CGImageGetHeight(inImage);
 
	// Declare the number of bytes per row. Each pixel in the bitmap in this
	// example is represented by 4 bytes; 8 bits each of red, green, blue, and
	// alpha.
	bitmapBytesPerRow   = (pixelsWide * 4);
	bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);
 
	// Use the generic RGB color space.
	colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
	if (colorSpace == NULL)
	{
		fprintf(stderr, "Error allocating color space\n");
		return NULL;
	}
 
	// Allocate memory for image data. This is the destination in memory
	// where any drawing to the bitmap context will be rendered.
	bitmapData = malloc( bitmapByteCount );
	if (bitmapData == NULL)
	{
		fprintf (stderr, "Memory not allocated!");
		CGColorSpaceRelease( colorSpace );
		return NULL;
	}
 
	// Create the bitmap context. We want pre-multiplied ARGB, 8-bits
	// per component. Regardless of what the source image format is
	// (CMYK, Grayscale, and so on) it will be converted over to the format
	// specified here by CGBitmapContextCreate.
	context = CGBitmapContextCreate (bitmapData,
									 pixelsWide,
									 pixelsHigh,
									 8,      // bits per component
									 bitmapBytesPerRow,
									 colorSpace,
									 kCGImageAlphaPremultipliedFirst);
	if (context == NULL)
	{
		free (bitmapData);
		fprintf (stderr, "Context not created!");
	}
 
	// Make sure and release colorspace before returning
	CGColorSpaceRelease( colorSpace );
 
	return context;
}

[Slashdot] [Digg] [del.icio.us] [StumbleUpon]

UITables with Downloaded Images – Easy Asynchronous Code

Readers… do look through the comments if you plan to use this code, other people have posted improvements. Thanks for all the great feedback everyone. MJ

postcards-screen1The app ‘Postcards’ from my iPhone developer training class is a utility app for quickly sending a customized postcard, and one thing that makes it super easy is that you can grab pictures from Flickr to include in the postcard design. Postcards makes simple HTTP calls Flickr’s REST API to download public domain images and displays them in a UITableView for the user to pick from. Cocoa Touch makes this all simple and easy to code, and my first development version used synchronous calls to get the images by using NSData dataWithContentsOfURL:

.

.

NSData* data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urls]];

Making synchronous calls to remote web servers from the thread that’s running the apps GUI is of course a bad idea that results in a laggy UI and unsatisfied users. Using synchronous calls in UITableView cellForRowAtIndexPath to load all the images results in a problem six times worse (for 6 rows on the screen) and makes scrolling basically broken as the table won’t scroll until it has the next cell, which it can’t get while the app is waiting for an image to download. Then imagine that on the Edge network! Obviously we need something multi-threaded that can load the images in parallel in the background and update the UI as they finish downloading.

Multi-threaded programming is hard and should be avoided whenever possible, and in this case Cocoa’s beautiful design came to my rescue:

UIView heirachy + URL loading system + delegate design = multi-threaded image loading with no multi-threaded coding!

How can you have your cake and eat it too? Every iPhone app is a multi-threaded program, or at least its running in conjuction with the multi-threaded iPhone operating system. Use the right delegate methods in the right ways, and you can take advantage of extra threads of execution that the iPhone gives you for free without writting any multi-threaded code of your own, hence sidesteping the problem of threading bugs in your code. An iPhone app is one big event loop – your classes have methods that the event loop calls in response to stuff happening on the device and in your app. When you use the URL loading system’s asynchronous APIs, the iPhone uses a different thread than the one running your app’s event loop to load the contents of the URL, and it makes callbacks via your apps event loop when data has been downloaded.

connection = [[NSURLConnection alloc]
                          initWithRequest:request delegate:self];
 
- (void)connection:(NSURLConnection *)theConnection
                          didReceiveData:(NSData *)incrementalData

Note carefully, when data has arrived from the remote webserver, that other iPhone thread doing the downloading doesn’t make calls into your objects at the same time as your methods are running, it puts messages into your apps event loop. If it called your app directly then chances are your app would be running some UI code or something and you’d have to write thread safe code. Instead, the call that data is ready arrives as an event on the event loop. Events on the event loop run single threaded, one at a time. Using this we can get asynchrous image download from Flickr without writting thread safe code ourselves. Even better, Cocoa’s URL loading system will download those URLs in parallel! For free!

That’s all well and good, but how do you get a table view to update the UITableViewCell with the image after its already been returned? A UIImage is imutable (right?) so you can’t change its image later when the image data has downloaded. Turns out Apple made this super easy too. Instead of putting a UIImage in the UITableViewCell, you put your own UIView object, that is sized correctly for the image you want to display, into the content view of the UITableCell (as a subview). At first your view object it can be empty, or it can have a dummy image in it, or you can pop in one of those spinny ’something is happening’ views. Then when the image data is downloaded, create a UIImageView with the image and pop it in your view in the cell. Hey presto… it appears. While all this is happening the user can be scrolling and going back and forth with a fully functioning UI.

I put this all together in a class AsyncImageView, listed below. It’s use is simple

  1. alloc and initWithRect:
  2. add it to a view, eg in a table cell’s content view;
  3. send it the loadImageFromURL: message.

LoadImageFromURL will return right away, the image will load in the background, and will automatically appear in the view when its finished downloading. The code posted below is something I whipped up pretty quickly (and I didn’t leak check yet!), but hey – parallel, asynchronous image download and display in about 40 lines of code with no thread-safe worries? Works in smooth scrolling tables, even on the Edge network? I rate it a big win, and wanted to share the technique.

I’ve developed an iPhone programming training class that I will be teaching soon in the SFBay Area (though my partners and I could probably bring it to you). It’s very hands on, and specially designed to help professional programmers new to Cocoa and Objective-C over the difficult initial learning curve. In the class we build the Postcards app from start to finish, including AsyncImageView. Email me for more info: markj at markj.net

AsyncImageView.h

AsyncImageView.m

@interface AsyncImageView : UIView {
    NSURLConnection* connection;
    NSMutableData* data;
}
@end
 
@implementation AsyncImageView
 
- (void)loadImageFromURL:(NSURL*)url {
    if (connection!=nil) { [connection release]; }
    if (data!=nil) { [data release]; }
    NSURLRequest* request = [NSURLRequest requestWithURL:url
             cachePolicy:NSURLRequestUseProtocolCachePolicy
             timeoutInterval:60.0];
    connection = [[NSURLConnection alloc]
             initWithRequest:request delegate:self];
    //TODO error handling, what if connection is nil?
}
 
- (void)connection:(NSURLConnection *)theConnection
     didReceiveData:(NSData *)incrementalData {
    if (data==nil) {
          data =
          [[NSMutableData alloc] initWithCapacity:2048];
    }
    [data appendData:incrementalData];
}
 
- (void)connectionDidFinishLoading:(NSURLConnection*)theConnection {
 
    [connection release];
    connection=nil;
 
    if ([[self subviews] count]>0) {
        [[[self subviews] objectAtIndex:0] removeFromSuperview];
    }
 
    UIImageView* imageView = [[[UIImageView alloc] initWithImage:[UIImage imageWithData:data]] autorelease];
 
    imageView.contentMode = UIViewContentModeScaleAspectFit;
    imageView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth || UIViewAutoresizingFlexibleHeight );
 
    [self addSubview:imageView];
    imageView.frame = self.bounds;
    [imageView setNeedsLayout];
    [self setNeedsLayout];
    [data release];
    data=nil;
}
 
- (UIImage*) image {
    UIImageView* iv = [[self subviews] objectAtIndex:0];
    return [iv image];
}
 
- (void)dealloc {
    [connection cancel];
    [connection release];
    [data release];
    [super dealloc];
}
 
@end

And here is the usage in UITableViewCell. The AsyncImageView gets tagged with 999, and when it gets recycled, that 999 tagged view gets fished out and removed. So only the cell is being recycled, not the AsyncImageView object. When its removed from the cells content view it also gets released, causing dealloc, which in turn cancels the url download (if its outstanding).

- (UITableViewCell *)tableView:(UITableView *)tableView
       cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
    static NSString *CellIdentifier = @"ImageCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 
    if (cell == nil) {
        cell = [[[UITableViewCell alloc]
              initWithFrame:CGRectZero reuseIdentifier:CellIdentifier]
              autorelease];
    } else {
	AsyncImageView* oldImage = (AsyncImageView*)
             [cell.contentView viewWithTag:999];
	[oldImage removeFromSuperview];
    }
 
	CGRect frame;
	frame.size.width=75; frame.size.height=75;
	frame.origin.x=0; frame.origin.y=0;
	AsyncImageView* asyncImage = [[[AsyncImageView alloc]
               initWithFrame:frame] autorelease];
	asyncImage.tag = 999;
	NSURL* url = [imageDownload
               thumbnailURLAtIndex:indexPath.row];
	[asyncImage loadImageFromURL:url];
 
	[cell.contentView addSubview:asyncImage];
 
    return cell;
}

[Slashdot] [Digg] [del.icio.us] [StumbleUpon]

Best Books for iPhone Development

Some brilliant iPhone developer books are out now which are great for learning iPhone native app and web development, and handy references for existing Cocoa Touch experts. In this article I review several titles and give you my pick of the best for learning the native SDK and Objective-C programming:

iPhone in Action

iPhone in Action has very broad coverage of developing for the iPhone, and it introduces everything you need to know. The first third of the book covers web stuff – both how to revamp your existing website so it works great on both the desktop and iPhone, and also how to create iPhone specific web apps. Topics include design, CSS, iUI (the awesome library to make native looking web apps), graphics with webkit canvas, Dashcode, and debugging tips. The middle third of the book gets you started with native SDK development, starting with an overview of Objective-C and XCode, and then on to lots of good step by step tutorials for learning how to use Interface Builder and the different kinds of view controllers to create your GUI. The final third is an intro to important SDK programming topics including graphics, web interaction, SQLite databases, using the address book, etc. The book is invaluable for beginners because it shows you all the possibilities of both web and SDK and it introduces all the key topics – something no other single title does. Experts will want this title too for the detailed web development topics.

Beginning iPhone Development – Exploring the iPhone SDK

This fantastic book is an APress title, I don’t know how they do it but APress has great authors and every APress book I get is a home run. The book explains how to use the Cocoa SDK to write iPhone apps in very clear easy to digest steps. It has a lot more detail and an easier pace than ‘iPhone in Action’. View controllers are the most important part of the SDK to get to grips with, and they are the hardest to figure out. In this title we get 200 delicious pages devoted to them, compared to just 60 in ‘iPhone in Action’. ‘Beginning iPhone Development’ only covers the SDK and Interface Builder, so it has room for some useful SDK topics you won’t find written about elsewhere like UI’s that rotate to landscape mode and localization for different countries. This is the best book for learning native iPhone development.

Learn Objective-C on the Mac

Also on APress, this is _the_ book for learning and mastering Objective-C. Great writing, very easy to understand, and excellent as both a tutorial and reference. The authors assume you already know a little C syntax (from C, C++, Java, etc), so this is the key text for switchers. Still not figured out memory management retain counts and auto-release pools? Protocols, categories and inheritance a mystery? It’s all in this book. Recommended for all iPhone developers.

The iPhone Developer’s Cookbook

A great collection of recipes for using the SDK in the form ‘how to make my iPhone app do X’ format. These programming nuggets are lying on the page waiting for you to pinch ‘em and drop right into your own apps saving lots of time and giving you some great new ideas. Beginners and experts alike will learn many new tricks, everything is explained with clarity and brevity. For example after just 1 hour with this book I realized that my own app had buggy table views that I was able to easily fix using recipes from the book. Some of the recipes even mention undocumented APIs that allow neat UI details you’ve seen in Apple’s apps but otherwise couldn’t figure out how to do. This book should stay by any iPhone developers side.

…and a few more

Here are some additional books you might find helpful

‘Learn C on the Mac’. If you’ve never programmed any C or C++ you might also want to check out this book, also on Apress. Some iPhone programming is done with are pure C APIs, eg SQLite, Quartz 2D Graphics, OpenGL, and there’s also a lot of use of C structs throughout Cocoa. To use these you’ll have to get your C pointers syntax right, and of course Objective-C is a super set of C anyway, so brush up your C.

Programming in Objective-C. This comprehensive reference covers  everything about the language, both the C and Objective-C parts.

Cocoa Programming for Mac OS X (third edition), Aaron Hillegass. OK, this isn’t an iPhone book, its a Mac programming book, and this is the book I learned Cocoa and Objective-C from before all the iPhone books came out! There’s a lot in common between iPhone development and Mac development, so if you are confused and want to read the basics explained with a different voice, this is somewhere you can turn. Let’s hope the author comes out with an iPhone version.

XCode Unleashed Fritz Anderson. New to Apple development means new to XCode, so if you want a book to help you make XCode bend to your will, this is where to turn. While you might not want to read 500 pages about an IDE, its good to have as a  reference, for learning a few productivity tricks, and it includes lots of information on debugging, Shark and Instruments, source code control, unit testing, documenting your code, etc.

Apple’s Documentation. Of course you don’t need a review of Apple’s extensive and free documentation because you already read it all right? No? You got lost and gave up once you started trying to write your app? (I did at first.) With one or all of the books above to get you going, dip back into Apple’s excellent documentation for lots more gory detail. Once you’ve got the hang of  Cocoa and Objective-C you’ll see that Apples documentation is excellent, and you’ll be hitting command-option-shift-/ all the time in XCode. As well as all the API documentation, pay special attention to the Human Interface Guidelines, breaking these guidelines can get your app rejected.

[Slashdot] [Digg] [del.icio.us] [StumbleUpon]

  • Categories

  • markjnet