Go To Homepage



Book Details
Beginning iPhone Development: Exploring the iPhone SDK book cover
  • By Dave Mark Jeff LaMarche
  • ISBN13: 978-1-4302-1626-1
  • ISBN10: 1-4302-1626-3
  • 536 pp.
  • Published Nov 2008
  • Print Book Price: $39.99
  • eBook Price: $27.99



Errata Submission

If you think that you've found an error in Beginning iPhone Development: Exploring the iPhone SDK, please let us know about it. You will find any confirmed erratum below, so you can check if your concern has already been addressed.

Submit Errata
Beginning iPhone Development: Exploring the iPhone SDK (978-1-4302-1626-1)

Errata

Issue Author's Response
First, let me say, this is literally the best book of this kind that I've ever read -- no kidding. Smoking Hot, guys!!!!
Now here are a few thing that I think are mistakes:

1. Page 63. The bottom paragraph doesn't flow. The paragraph reads: "...,grab a label from the library, and drag that over so it is aligned with the left margin of the view and aligned vertically with the text field you placed earlier." Maybe you meant align horizontally with text field we placed earlier.

2. Page 85. Sample code for viewDidLoad. The first line has "jmUIImage" when I'm sure you meant "UIImage" without the "jm" in front of it.

3. Page 109. Wanted to let you know that I did not need to add the CoreGraphics framework, when I opened the Resources section the CoreGraphics.framework was already there. I decided to test this with the compile and it compiled and ran fine. Hmmm, maybe Xcode 3.1.2 is now smart enough to realize I needed the framework and add it for me -- but of course I didn't look to see if it was there at initial creation of the Project or if it was added once it saw the core image code references.

4. Page 106 and 107. Are the CGRectMake numbers correct? Wouldn't Portrait use 320 and 460. Also Landscape would use 480 and 300 -- correct???

Take care and AWESOME work guys.

best regard
Dalton Hamilton
Dalton - thanks for the kind words, we appreciate it, and thanks for taking the time to submit these.

Page 63 - you are 100% correct, that should be "align horizontally" with the ones placed earlier.

Page 85 - Yeah, this one's already in the errata system, caused a lot of people headaches.

Page 109 - Apple added CoreGraphics to the standard project templates some time after the release of the book. We'll remove the instructions to add it in future editions.

Page 106 and 107 - Yeah, the portrait on page 10 should

self.view.bounds = CGRectMake(0.0, 0.0, 320.0, 460.0);

So should the one on page 107 under UIInterfaceOrientationPortraitUpsideDown, it should be the same.

And the two on page 107 UIInterfaceOrientationLandscapeRight and UIInterfaceOrientationLandscapeLeft it should be

self.view.bounds = CGRectMake(0.0, 0.0, 480.0, 300.0);

Thanks,
Chapter 6, page 126
[self.view insertSubview:blueController.view atIndex:0]
should be:
[self.view insertSubview:blueViewController.view atIndex:0]

Your book is great, and I can't wait for the Cocoa book to come out
You are correct, sir. It should be blueViewController not blueController in both spots in that blueController appears (the release, and the insertSubview). Thanks!
Ch 4, p 65, 6th paragraph, last sentence reads: "Uncheck this if it's checked, or just leave it as is if it's checked." :) Wow, we said that? I guess we did. :)

Yeah, that last word in the sentence should, of course, be "unchecked", not "checked". We'll get it fixed next time we do a revision.
Chapter 9 Page 263.

When running the Application Under iPhone OS 2.2 changing the slider state will result in showing the UIAlertView prior to the value being changed even though on the screen it looks like it has been changed. Switching to iPhone OS 2.0 does not cause this so it looks to have been a change in the SDK. I've been poking around trying to figure out how to make the alert not fire in the case of a change but have been unsuccessful so far. the accessoryButtonTappedForRowWithIndexPath does not appear to be called whenever a control is used as the accessoryView.

A note in future editions would probably be worthwhile.
This example is probably going to be revised in future editions, as using a switch (as opposed to, say, a button) opened up some issues that we didn't want to discuss until later in the chapter, such as the idea of maintaining state for the table because of the dequeuing behavior. Future editions will probably just have a button here, although it does seem to raise a concern when putting a control in the accessory view.

I will have to investigate a little to determine if this should be a bug report and, if not, what the best way to deal with it is, but here's one possible way:

In RowControlsController.h, add a BOOL instance variable called controlUsed and an action method:

#define kSwitchTag 100

#import <UIKit/UIKit.h>
#import "SecondLevelViewController.h"

@interface RowControlsController : SecondLevelViewController
<UITableViewDelegate, UITableViewDataSource> {

NSArray *list;
BOOL controlUsed;

}
@property (nonatomic, retain) NSArray *list;
- (IBAction)controlPressed;
@end

This variable will be used to identify if a control was just pressed. The action method will be called when the switch is touched and will set controlUsed to YES.

Here is the implementation of the method:
- (IBAction)controlPressed
{
controlUsed = YES;
}

Since we're not using a Nib file, when we create the cells, we'd have to set the target for the switch, and we'd want to use the UIControlEventTouchDown so that as soon as the switch was touched, the controlUsed gets set to YES. Here is the current version of tableView:cellForRowAtIndexPath: with the code to set the target:

- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *ControlRowIdentifier = @"ControlRowIdentifier";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ControlRowIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:ControlRowIdentifier] autorelease];
UISwitch *switchView = [[UISwitch alloc] init];
[switchView addTarget:self action:@selector(controlPressed) forControlEvents:UIControlEventTouchDown];
switchView.tag = kSwitchTag;
cell.accessoryView = switchView;
[switchView release];
}
//////////////////////////////////////////////////////////////////
// NOTE: In this example, we are not keeping track of the state
// of the switch. As a result, if our list were longer, we
// would lose because the table view would dequeue the cell
// with the switch in it. This is okay when you know your
// table view's list will be small, but generally, you'll
// want to keep track of any state in your application's
// data model and shouldn't rely on table view cells to
// hold onto values for you. For simplicity's sake, this
// example doesn't have a data model, but in the last
// subcontroller, you'll see how to store the data rather
// than relying on the table view cell, which could get
// dequeued.
//////////////////////////////////////////////////////////////////

NSUInteger row = [indexPath row];
NSString *rowTitle = [list objectAtIndex:row];
cell.text = rowTitle;
[rowTitle release];

return cell;
}

Finally, tableView:didSelectRowAtIndexPath: would have to be modified to only fire if controlUsed was NO, and also to reset controlUsed for the next press. Here are the changes to that method:

- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (controlUsed)
controlUsed = NO; // Reset for next use
else
{
NSUInteger row = [indexPath row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UISwitch *switchView = (UISwitch *)[cell viewWithTag:kSwitchTag];

NSString *baseString = @"%@ %@.";
NSString *onString = (switchView.on) ? @"IS on" : @"IS NOT on";
NSString *robot = [list objectAtIndex:row];
NSString *messageString = [[NSString alloc] initWithFormat:baseString, robot, onString];

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Row Selected."
message:messageString
delegate:nil
cancelButtonTitle:@"Thanks!"
otherButtonTitles:nil];
[alert show];
[alert release];
[messageString release];

}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

Now, this may not be a final solution, but it does work, so hopefully it will tide anyone over until we can determine if this is a bug or just changed behavior.
Chapter 5, Page 111

In the tip section you say to Right click the Resources folder. I think you would want to Right click the Frameworks folder and add the framework under that so they would all be together.
You are correct, that should say Frameworks folder instead of Resources folder. We'll make sure it's changed the next time we revise the book. Thanks!
Chapter 5, Page 101-102

Not sure if this is maybe a result of new SDK but the animation works in the Simulator w/o having to add the 2 lines provided. Adding them doesn't seem to change the effect at all.

----

If I could make one suggestion it would be to rearrange this page to be in Chapter/Page order so it's easier to find known issues. Or at least standardize the Chapter/Page line so it's searchable.

Great book so far. Thanks.
Chapter 5 - yeah, a last minute change recommended by Apple to address one of the bug reports we filed was to move the code from another notification method. I think we originally had it the code willRotateToInterfaceOrientation:duration: which worked, but was jarring in its appearance, which is why we chose to show animation blocks at the time to smooth the transition.

Right before the book went to press, Apple suggested that we move the code to its present location, but we didn't realize when we made the change that the new method is inside of an implicit animation block, which means that the two lines added on 101-102 don't actually change anything because we're already in an animation block.

The basic idea is correct and can be used in other places (putting changes to view properties between those calls), however in future editions, we'll have to show this somewhere else where it actually makes a difference.

Sorry about the confusion.

Also, these errata reports come to the author - but concerns about the errata system itself and how it works should probably be sent to editorial@apress.com, because we don't have any control or authority over that. Thanks.
Great book!

Some minor stuff I did not see in your errata...

Chapter 4, Page 65, Paragraph 6:

It says "Uncheck this if it's checked, or just leave it as is if it's checked." I guess it is just be sure it is unchecked.

Chapter 4, Page 75:

I am new to Apple development tools and as your Caution Note in this page about Code Sense is welcomed, it seems somehow late, because I have seen that behavior since I started the first sample code.

Chapter 4:

Not really an issue with the book, but I found the behavior of the Segmented Control kind of odd. If I click on Hide, it will work as expected, but if I click Hide again, the Show option gets activated. It is probably the standard behavior of the control, but do not seems obvious.
Thanks for the kind words:

Page 65: This one has already been reported, we'll get it taken care of

Page 75: That is a good point, we'll take a look at moving it earlier in the book when we next update the layout if it's feasible to do so.

Chapter 4 - Yeah, this is the standard behavior of the control, and year, it's different than a tab controller on the desktop, which can be confusing. We should look at adding a comment about that so that people aren't confused by it. My assumption is that this behavior was chosen because of the imprecise nature of touch detection, but that's just a guess.

Thanks again,
Jeff
Chapter 9, page 235
Figures 9-6 and 9-7 back buttons show a root view controller with title "Top Level".
The other Figures (9-3, 9-4, 9-5) are consistent with Figure 9-2's title of "Root Level".
You are correct - 9-6 and 9-7 should be re-shot to show "Root Level" - our initial draft of the chapter used "Top Level", but because it's actually the bottom of the navigation stack, we were concerned that it might cause confusion to have something be both the top and bottom. We'll get those screenshots re-shot for the next time we're able to update the book. Thanks.
Love the book. You guys did a great job with it. Chapter 6, Pg 126. In the third paragraph, where you instruct us to "Control-drag from the View_SwitcherAppDelegate icon to the SwitchViewController icon, and select the switchViewController outlet.", when I do that myself, I do not see any actions pop up. I've retraced my steps through the whole chapter and do not see where I've gone wrong. Not sure what I've missed. Since you mention "icon" each time, I gather that you're talking about the icons in the MainWindow.xib window, right? Thanks for any help. If you send me your project to jeff@iphonedevbook.com I'll be happy to look at it and see if I can't figure out why it can't find the action. If your instance variable switchViewController has the IBOutlet keyword before it, it should pop up in Interface Builder when you follow those instructions. What you're describing can happen if the class of the object you dragged to doesn't match, or if there was a problem parsing the header file, but in the latter, it should show up as a warning or error when you compile the project.

I can probably figure it out pretty quickly if you send me the actual project.
Chapter 8 : Page 208
old: cell = [nib objectAtIndex:1];
new: cell = [nib objectAtIndex:0];

poorly stated explanation:
Array index handling was changed by Apple with SDK 2.1+ to point to record 0. In version 2.0 and older,
data started at record 1.
Can you please re-submit with your specific objection or where this needs clarification - I don't fully understand your concern. There was a change at SDK2.1 - the first object instance from the nib prior to that was located at index 1 (there used to an entry for the proxy object File's Owner at index 0), from 2.1 on, the proxy object is no longer there, and the first object instance in the nib is now located at index 0.
chapter 7, bottom of page 167
currently shows this text:
[picker selectRow:0 inComponent:kZipComponent animated:YES];
[picker reloadComponent:kZipComponent];

The object named in the formal arguments to the method is pickerView, not picker; `picker' is the class's only instance variable of type UIPicker *, so in this case it works, but in general I would recommend teaching new programmers to use the argument passed to them.
You are right that you could accomplish the same thing by using the pickerView method argument instead of the instance variable picker, however the use of picker here was intentional, not an accident.

There are times when using the method argument over the instance variable (or vice versa) matters. Here (as you've pointed out) it doesn't since picker must equal pickerView unless there is a bug.
Chapter 9, page 323

"You might be wondering why we chose viewDidAppear: instead of viewWillAppear:... The viewWillAppear: method of that controller will actually get called before the viewWillDisappear: of this controller"

Chapter 9, page 326

"Because our controller’s viewWillDisappear: method will fire before the main view’s viewWillAppear: method"

Could you please clarify the order of execution of the methods, and to which controller? It is not clear and there seems to be a contradiction between pages 323 and 326 as to whether -viewWillDisappear: gets called first or not.
The order, which you can actually see by looking at the toggleView method in the RootViewController.m file, is

viewWillAppear: of the new view's controller - the one that is going to be shown gets called
viewWillDisappear: of the controller for the view currently being shown gets called

then the views are swapped, then

viewDidDisappear: of the controller for the view that was being shown, but has now been swapped out gets called
viewDidAppear: of the controller for the view that was just swapped in gets called.

So, basically, the order is context sensitive - it depends on which one is being swapped in and which is being swapped out.
Ch.4, p 67: I compiled and ran but on clicking inside the name or number field, the keypad DOES not pop up.! I am sure I have set attributes exactly mentioned in text book. Hop over to http://iphonedevbook.com and go to the forums. Dave and I answer questions there, and I think we're going to need to get more information from you on this one to figure out why it's not working.

Did the version of the project in the download file do the same thing?
Chapter 15: Wheel, Page 449

2nd paragraph after the code listing, it said "....Change the view's height from 460 to 480 so that it takes additional screen space made available by getting rid of the status bar."

I couldn't change the view's height from 460 to 480 only until I changed "status bar" to "none" at the "View Attributes" window of "Simulated Metrics". I am using Xcode 3.1.2.
Hmm... I remember this happening at one point - not sure if happened at the 2.1 or the 2.2 SDK update, and don't know if it will stay that way, but we'll definitely walk though all the instructions before we issue a new edition and will make a note of this if it's still the case.

Thanks!
Jeff
Hi,
A couple of more things re page 208 in print edition. The tableView delegate method tableView:heightForRowAtIndexPath is really for when you wish to have rows with varying heights in the same table. tableView has a property rowHeight which can be set in IB in size inspector or programatically for tableViews created that way or ones created in IB and given an IBOutlet.

You probably already knew this but just in case. You may have even used it in other parts of the book since I am skipping around.

I love your IB stuff. Most of apple's doc gives short shrift to IB and all of their sample code doesn't use it. So you are the oracle.

Thanks Thanks Thanks
Thanks for the heads up and for the kind words.. I don't think we actually discuss the rowHeight property, but when we go to update it, we'll definitely look at including it.
P208 of print copy has an error that has already been reported. The return statement at the end of the page s/b" return kTableViewRowHeight; ". As I said this has already been reported but in your response to the submission you misspelt kTableViewRowHeight. Sorry but I thought you might like to know.

I like your book. I wish I had had it in march when I was teaching myself all of this. In fact I wish i had even had a bit of your wisdom and started with your Learn C on the macintosh book first, then the learn objective c on the macintosh book and finally this book. Alas i started with Learning Cocoa with Objective C, a real slog for someone with no programming experience. I followed this with Building Cocoa Applications and finally Cocoa Programming for OSX second edition. Then i moved on to Apple's documentation.

Finally this fall I had some time to kill so I read and did Mark 's Learning Objective C on the mac. Followed by your book learning C on the mac. Boy what a dope I was!! Anyway now anyone smart enough to start with your book first followed by Marks and then this book can learn what took me months in probably just a few weeks.

The first two books I mentioned re cocoa I would not recommend, except perhaps for someone looking for new insights - definitely not good primers ; but Aaron Hillegass's book was great as is programming in objective C by Kochan.

You guys are great!! Thanks for all your help. I wish I knew you.
Thanks for the kind words. We'll make sure that the next edition goes out with kTableViewRowHeight; spelled correctly.

Feel free to stop by the http://iphonedevbook.com forums, both Dave and I are there regularly chatting and answering questions. You can also meet me at either MacWorld or WWDC in 2009. Not sure what Dave's conference schedule is for the year, but I'll definitely be at both.

Follow me on twitter to find out where I'll be at the cons - http://twitter.com/jeff_lamarche and you can follow my blog for more advanced iPhone topics at http://iphonedevelopment.blogspot.com
Awesome book. I've been loving it.

The code "errors" should be trivial to work through for anyone trying to use the book. I actually like to have to think a little, especially by chapter 123 when it all starts to look so repetetive except for the new topics.

BUT!!!!! There is something fishy, or I'm not cleaning properly...

A few of the samples won't let me downlad to the iPhone, while most will. I have paid my $99 and do this all the time!

On only these failing onbes, I get:
Line Location Tool:0: CodeSign error: Code Signing Identity 'Jeff LaMarche' does not match any code-signing certificate in your keychain. Once added to the keychain, touch a file or clean the project to continue.

Specifically, so far, Swipes won't go to my iPhone, and nether will TouchExplorer. No problems on any other examples. I've verified that info.plist is the same... even dragged a perfect one into both projects.

I've deleted the pch files and cleaned the project.

It compiles just fine and runs on the sim, but no go for download.

Ideas?

Again, thanks for an amazing book. This is really helping me so much.
Ned Lecky
Have you changed the code signing identity in the Targets dialog? I assume you have, since you've gotten other projects to run.

If you have, then I'm not sure what to say. The code-signing stuff is touchy, sometimes it doesn't recognize when changes have been made. It could be due to changes Apple has made in Xcode between SDK 2.0, and 2.2. I've found the code signing to be problematic, but unfortunately, this is more of an Xcode issue than a book issue.

If worse comes to worse, you can create a new project and copy the code and nib files over, and that should work.
Chapter 4 Page 79

The code for adding the outlet and action to the Controller Header file shows an IBOutlet declaration for UIProgressView underneath the IBOutlet *sliderLabel. Its property is declared below. ??
You can ignore the UIProgressView. An earlier version of this chapter's application used one, and looks like we missed it. Fortunately, having unused outlets won't hurt anything, but they definitely shouldn't be there. (Good catch, by the way).

Chapter 4, Page 79

Remove the following two lines of code:

IBOutlet UIButton *doSomethingButton;

and

@property(nonatomic, retain) UIProgressView *progressView;
Im running through the second tutorial and on Page 78 Chapter 4 I have connected all of the outlets and built my project. But basically whenever i try and click either of the two segmented buttons an uncaught exception is thrown and terminates my program. Any ideas? I have double checked all my application logic and its fine!

Attaching to program: `/Users/absolutehype/Library/Application Support/iPhone Simulator/User/Applications/DB696FC6-1590-4ECA-B8DD-1AF6669DE5C7/AH Studios.app/AH Studios', process 7676.
(gdb) continue
objc[7676]: objc_exception_throw failed
Program received signal: “EXC_BAD_INSTRUCTION”.
(gdb)
It's hard to say - I just tested the project for chapter 4, and this problem doesn't happen for me. Have you tried compiling the version in the project archive? You can download it from http://iphonedevbook.com

This is a particularly hard error to debug because it's an indication that some illegal instruction is being used, which usually happens at the compiler level. Try doing a "Clean All" and re-building your application, and try our version. If it does it with our version, then it's probably something with your developer tools install, and you may need to reinstall them.
Chapter 8 pg 199 (225 of the eBook)

2nd paragraph, 2nd sentence

should UITextViewDelegate be UITableViewDelegate?
Yes, it definitely should be.


Chapter 8 pg 199 (225 of the eBook), 2nd paragraph, 2nd sentence
UITextViewDelegate be changed to UITableViewDelegate
You have written a beginners book and it would be real nice for you to update the PDF file so we as beginners could get a new version of the book without the vast errors. We have spent hours trying to debug your code, and get so frustrated that we move on to the next chapter. I think this is very simple for you to do as other publishers do this. Thanks I'm sorry - I agree with you, but this complaint needs to go to Apress - Errata goes to the individual authors, and we do our best to fix them when we become aware of them, but we are not the ones who maintain or update the PDF files.

Please contact Apress at editorial@apress.com with your concerns.
Chapter 7, Page 175

The NSString "arrayName" is in pickerView:viewForRow:forComponent:reusingView: is never released.
You are correct - good eye! After the line that reads

NSArray *array = [self valueForKey:arrayName];

Should be this line

[arrayName release];
Chapter 6: Page 121: Second line of code listing has

@class View_SwitcherAppDelegate; with strikethrough font...

What is the significance of the strikethrough? This line was not in my class after following the instructions to that point.

Also, a few lines down IBOutlet UIWindow *window is listed in plain text (not bold) and yet in my class generated by XCode, there is no IBOutlet on that line... If IBOutlet is needed there, shouldn't it be bolded?
That line of code used to be added by the template. We submitted a bug reports to Apple and they appear to have taken the code out.

The application delegate should have an IBOutlet for the Window in any of the templates, so I'm surprised it's not there - perhaps it got deleted accidentally? I just created a new project, and that line of code was created for me even under 2.2.
At the end of page 75 the book show:
BOOL setting = whichSwitch.isOn;
but is (as you source code zip file)
BOOL setting = [whichSwitch isOn];
These two lines of code are functionally identical. For consistency's sake, we will change the project to match the book.
Chapter 4 Page 75
Clicking on either switch changes both switches to same value. I think they should be independent of each other.
The example is not, admittedly, very realistic, but it allowed us to show how to change a switch programmatically and to demonstrate how that change can be animated without much effort. Had we made the switches independent, we could not have shown either of those.

If you wish to change your application so that the switches are independent, just comment out the contents of the switchChanged: method, and the two switches will become independent.
Chapter 9, p.247

This may not be critical, but in the downloadable file,
- (id)initWithNibName: ...
is being used instead of
- (id)initWithStyle: ...
as in the book.
The difference between the book code and the project's code will have no impact on the application since we do not do any initialization in this class. That particular code was untouched from what was provided by the file template. I think in an earlier incarnation of the project, we subclassed UIViewController instead of UITableViewController (as the book says to do) and the different method signature is (if I recalll) owing to that.

For consistency's sake, I will update the project to contain the same methods as the source code
Chapter 10, p.311
6th paragraph, 1st line

"Expand Item 2." should not be here.
The paragraph is explaing "Item 1", as its Type is PSGroupSpecifier.

The following sentence,
"The first row under it has a key..."
would read better if it explicitly says
"The first row under Item 1 has a key ..." .
Reader's change is correct.

Chapter 10, p.311 remove "Expand Item 2" from sixth paragraph. Change the next sentence to read "The first row under Item 1 has a key of [i]Type[/i], and every...
Chapter 11, p.346
In - (id)copyWithZone:(NSZone *)zone ,
field1 = [self.field1 copy];
...
should be
copy.field1 = [self.field1 copy];
....
No, the code in the book on page 346 is correct.

Doing it your way would leak memory. The copy method returns an object with a release count of 1. Since the field1 property is declared with the retain keyword, then using the mutator would cause the retain count to go to 2. When that object was later released by the assignment of a new value, or during the dealloc method, it would only return it back to 1, meaning it could never be deallocated, and would tie up memory until the program quits.

If you feel the need to use the mutator method, you could alternatively use:

field1 = [[self.field1 copy] autorelease];

but I do not recommend it since it causes unnecessary use of the autorelease pool.
Could you explain how to get rid of this error

CodeSign error: Code Signing Identity 'Jeff LaMarche' does not match any code-signing certificate in your keychain. Once added to the keychain, touch a file or clean the project to continue.

So I can compile many of the examples in the debug mode on my touch?
You have to join Apple's iPhone developer program and pay your $99. Once you've done that, Apple will give you instructions (via the developer program portal) on how to run and debug your applications on your iPhone Touch.

Until you've been accepted into the program and created your own certificate, provisioning profile, etc., you will be unable to run your programs on any physical device and will be limited to the simulator.
Chapter 9, p.259
With this code, if you turn on R2-D2 and scroll down, you see that Tobor is turned on also. This is because the code is relying on switch setting to be kept by each cell and the cells get recycled. The switch settings should be kept separately in NSArray, or in NSDictionary together with robot names.
Yeah, we realized this after we sent it off to be printed and added a comment to the source code about it. Chalk this one up to the law of unintended consequences.

We designed this chapter so that each new controller we built was slightly more complex than the one before it. We did not intend to have a need for a separate data model until the next controller after this one - the point of the RowControlsController was simply to show that you could embed UIControl subclasses in the accessory pane.

Using switches for this controller was a poor choice given what we wanted to show. To do it properly, we not only have to keep state in a separate array or dictionary, but we also have to be able to retrieve subviews of the cell's content pane.

In the later examples in the chapter, we show how to keep track of state in separate arrays and then set the values of the cell's subviews to reflect that state, but we'd like to avoid doing that for this example and making an already long chapter even longer. I think in future editions, we'll switch to using buttons instead of switches.
Chapter 3, page 34
missing from text but in example file
IBOutlet UIButton *leftButton;
IBOutlet UIButton *rightButton;

@property (retain, nonatomic) UIButton *leftButton;
@property (retain, nonatomic) UIButton *rightButton;

Chapter 3, page 38
missing from text but in example file
@synthesize leftButton;
@synthesize rightButton;

missing from text but in example file
[leftButton release];
[rightButton release];

Chapter 3, page 51
A control drag from each button to the File's Owner icon seems to be necessary
There is no need for an outlet to either leftButton or rightButton. I will make sure these outlets are removed from the sample project archive, but the source in the book for chapter 3 (as far as outlets go) is correct.
Chapter 6, p119

Everything else we need for our application, we will have to have to create.

Should read:

Everything else we need for our application, we will have to create.
Yep, submission is correct:

Chapter 6, p119

Everything else we need for our application, we will have to have to create.

Should read:

Everything else we need for our application, we will have to create.
Chapter 5, page 106

The provided swap example does not work correctly in the iPhone Simulator. After rotating the view to landscape and back to portrait the buttons are redrawn incorrectly (only Foo is shown). After repeating the rotation both buttons are disappeared on the portrait view. This also applies to the downloadable example code.

Note: I can not test this bug on a physical iPhone yet, since I don't have a developer license.
That's odd - somehow an old version of the code got included in the project. I will update the source code project with the correct code.

The code from the book works fine.
Chapter 15, p457

Immaterial to the actual operation of the Ball application, but for consistency's sake, the second statement in the listing on this page should end with:

"currentPoint.y + image.size.height);"

instead of:

"currentPoint.y + image.size.width);"
Good eye! You're right.

On page 457, the setCurrentPoint: method, this code:

CGRect currentImageRect = CGRectMake(currentPoint.x, currentPoint.y, currentPoint.x + image.size.width, currentPoint.y + image.size.height);
CGRect previousImageRect = CGRectMake(previousPoint.x, previousPoint.y, previousPoint.x + image.size.width, currentPoint.y + image.size.width);
[self setNeedsDisplayInRect:CGRectUnion(currentImageRect, previousImageRect)];

should actually be:

CGRect currentImageRect = CGRectMake(currentPoint.x, currentPoint.y, currentPoint.x + image.size.width, currentPoint.y + image.size.height);
CGRect previousImageRect = CGRectMake(previousPoint.x, previousPoint.y, previousPoint.x + image.size.width, currentPoint.y + image.size.height);
[self setNeedsDisplayInRect:CGRectUnion(currentImageRect, previousImageRect)];
chapter 4

for the sake of continuity and consistency, you should release all control objects you synthesize in this chapter in the dealloc method of your view controller. Of course, nothing will happen if you don't but I guess it's good programming style...
You are absolutely correct, I can't believe we all missed that in this chapter! I'm updating the online project with the correct dealloc method and and explanatory note, and we will look at incorporating it into the text with the next edition.

In ControlFun for Chapter 4, the Control_FunViewController.m file should have a dealloc method that looks like this:

- (void)dealloc {

[nameField release];
[numberField release];
[sliderLabel release];
[leftSwitch release];
[rightSwitch release];
[switchView release];
[doSomethingButton release];

[super dealloc];
}
Chapter 12, Control Fun sample files

QuartzFunView.m, currentRect method

final portion of return command is currently

"fabsf(firstTouch.y - lastTouch.y);"

should have an extra closing paren:

"fabsf(firstTouch.y - lastTouch.y));"
Good catch. I'll make the change and submit a new version of the code. It will likely take at least a few days for the change to take effect.
Chapter 9, page 288 and 289

You use `@selector(textFieldDone:)` in the addTarget call, but use the instance method textFieldDidEndEditing:
There are two separate methods in this class. On page 28, there is a very short, one line method called textFieldDone: - that method is used to hide the keyboard. The textFieldDidEndEditing: instance method is part of the UITextFieldDelegate protocol and is used to keep track of changes made to the current first responder. textFieldDidEndEditing gets called automatically by virtue of setting this class to be the text field's delegate.

The code in the book is correct. When the user is done editing a field
Note: "page 265"

I said "Chapter 9, page 265. No pragma mark between data source and delegate methods"

You replied: "Page 255 doesn't have a code listing, only relevant excerpts from the previous code listing. The #pragma lines were not relevant to the discussion on page 255."

Note that `tableView:editingStyleForRowAtIndexPath:` is a delegate method, not a data source method
Ahh... there we go. Yes, on page 265, there should be another #pragma after tableView:cellForRowAtIndexPath and before tableView:editingStyleForRowAtIndexPath:

#pragma mark -
#pragma mark Table Delegate Methods
Chapter 9, page 295

It looks like `return cell;` in one of the code examples has an accidentally bolded n
Yep, the n should NOT be bold. Good catch.
Chapter 9, page 290

In the original code block on page 285, the save function uses `NSNumber *tagAsNum` but the code snippet discussing it here has `NSNumber *tfKey`
Although either version will work exactly the same, the code on page 290 should use the variable name tagAsNum to match the code in the project and the previous page.
Chapter 15, p453

Repeated references to BallViewViewController should be simply BallViewController
On page 453

both references to BallViewViewController.h and BallViewViewController.m should be changed to BallViewController.h and BallViewController.m
Chapter 9, page 265

No pragma mark between data source and delegate methods
Page 255 doesn't have a code listing, only relevant excerpts from the previous code listing. The #pragma lines were not relevant to the discussion on page 255.
Chapter 4, page 67

Figure 4-15 shows a version of the application with the slider control before the slider has been added which may be confusing given the context of ther "Build and Run" instruction on the current page.
In future editions, the slider will be removed from the 4-15 screenshot.
Chapter 4, page 57

New code in Control_FunViewController.h not shown in bold as it is in previous and subsequent examples of added code.
That is correct. This was intended as a test for the user to see if they could figure out the outlets for themselves. The text listing on the bottom of page 57 was not intended to show them how to do it, but rather to give them something to compare their code to after they were done.
Chapter 9, page 254

Using the 2.2 SDK (may be important), the line if `if (newRow != oldRow) {` doesn't work if lastIndexPath hasn't been set yet. I got around it by using
`NSUInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;`
int oldRow = [lastIndexPath row]

should be changed to

int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;
Chapter 9, page 255

Code example has:

[rowTitle release];

Which is not present in the original code. Also, the sentence above also makes reference to this non-existent rowTitle
any references to rowTitle should be removed. There is no such variable used in the method. The code listing on 253/254, the text on 255 is incorrect.
Chapter 8: Introduction to Table Views, page 205 and 206

In the code sample, the authors create 2 UILabel properties, which are synthesized in the CustomCell.m file. However, these properties are never released in the dealloc method on page 206. The following 2 lines should be added to the dealloc method on page 206, just before the line calling [super dealloc]:

[nameLabel release];
[colorLabel release];
Reader is correct. dealloc method should look like this:

- (void)dealloc {
[nameLabel release];
[colorLabel release];
[super dealloc];
}
Chapter 8, page 202

@"CellTableIdentifier ";

Has an errant extra space on the end (doesn't cause problems, obviously)
For neatness, should probably be changed to:

@"CellTableIdentifier";

As a unique identifier, there's no reason why this should (or shouldn't have a space). As long as it is unique, it will work correctly, but it will look better without the space.
Chapter 7, page 181

"The first method is use used to show"

"use" is an errant word
This should read:

"The first method is used to show"
Chapter 13, page 407. The note indicates that you have an Appendix A. I can't find it, and would like to prepare to connect Xcode to my device. I'm currently waiting for approval for acceptance into the iPhone Developer Program. So far, I received a message indicating that my request has been processed. In the meantime, the information provided in Appendix A might be useful for me. Thanks. Sorry, there is no Appendix A. One was planned, but then was decided against. We will remove references to this Appendix in later chapters. Please refer to the iPhone Dev Center for current information on getting applications to run on your iPod or iPhone Touch.
chapter 7
page 144

@class PickersViewController;

should be in bold to indicate that this should be added by user.
This line does not need to be added, and should not be in bold. This line of code used to be generated by the Xcode template, but current versions of the template do not create this line of code. The line of code is harmless: inoperative and unnecessary, but harmless.
chapter 7
page 148

declaration of buttomPressed is:

- (IBAction) buttonPressed;

Should be:

-(IBAction) buttonPressed:(id)sender;

chapter 7
page 150

implementation of buttonPressed is

-(IBAction)buttonPressed {...

should be

-(IBAction)buttonPressed:(id)sender{...

otherwise app crashes when the button is pressed.
While the use of

-(IBAction)buttonPressed:(id)sender;

is perfectly valid, the code in the book is valid as well. There are three valid signatures for action methods, and one of those valid method signatures is used in the book. Since we do not use the sender parameter, there is no reason to include it. There's no way to know why one version worked for the reader and the other didn't, but the code is correct in the book as published.
Chapter 7 / Page 144

I am following the instructions to the dot. (I have replicated the project 3 times, to be sure) and my
PickersAppDelegate.h does not have the line

@class PickersViewController;

since its not bold, I understand that this line should be automatically generated. It is not.
The project seems to compile with or without that line, although I cant get the iPhone simulator to display the views (but that may be a whole different issue, based on my n00b status)
I would appreciate a quick reply telling me why or how I am wrong.
Thanks for the effort you put into creating this GREAT book.
Hernan.
The line of code is not necessary and is no longer generated on current versions of the Xcode template used. Whatever problem you are having, it is unrelated to this line of code, unfortunately. Without more information, it's impossible to say what IS causing your problem.
Paperback Version
Chapter 4
Page 81

In Line 9 where it reads:
if (!buttonIndex == [actionSheet cancelButtonIndex])
the condition never became TRUE.

Only after adding extra ()s, the example worked as intended, like so:
if (!(buttonIndex == [actionSheet cancelButtonIndex]))

Otherwise excellent so far!!!
Page 81, Line 9 should read:

if (!(buttonIndex == [actionSheet cancelButtonIndex]))
Chapter 8, Page 214: Another reference to linking the Core Graphics Framework that is no longer necessary as of iPhone SDK 2.2 (9M2621). I no longer have the 2.1 or 2.0 SDK available, so I do not know when the template was updated to include this framework. If your project already contains a reference to CoreGraphics, then it is unnecessary to do this step.
Chapter 8, Page 208 -- In method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

the array that is returned by [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil]; no longer returns a reference to the files owner or other proxy objects in iPhone SDK 2.2 (Build 9M2621).

It looks like this is a simple case of how the SDK has grown between the time of printing and now! It is kind of a nit-picky issue but something that may trip up others new to Mac development.
Under SDK 2.0, the NSBundle method loadNibNamed:owner:options: returned an array that had, as its first object, a proxy object at index 0. I believe that this proxy object points to File's Owner, but I'm not sure of that, and if anyone knows better, please let me know. Whatever it points to, the existence of this proxy object meant that the first instance in the nib would be located at index 1, so when we grabbed the view in the tableView:cellForRowAtIndexPath: method in the book, we grabbed the object at index 1, which is the first (and only in our case) instance in the nib.

With SDK 2.1+, the behavior was changed so that no proxy object is included in the array. As a result, the index of the first instance in the nib now becomes 0 instead of 1. Since our nib only had one instances (excluding subviews), the array only had one object, meaning that index 1 was now out of range. The fix, is easy - just change
cell = (CustomCell *)[nib objectAtIndex:1];
to
cell = (CustomCell *)[nib objectAtIndex:0];

Here's the full method, using the availability macros to make sure it compiles correctly under all current versions of the SDK:

- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

static NSString *CustomCellIdentifier = @"CustomCellIdentifier ";

CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCellView"
owner:self options:nil];

// The behavior here changed between SDK 2.0 and 2.1. In 2.1+, loadNibNamed:owner:options: does not
// include an entry in the array for File's Owner. In 2.0, it does. This means that if you're on
// 2.2 or 2.1, you have to grab the object at index 0, but if you're running against SDK 2.0, you
// have to grab the object at index:0.

// You might be tempted to use UIDevice to get the system version number, however that is the
// operating system version, not the version of the SDK that the application is linked against. An
// iPhone operating running iPhone OS 2.2 can, for example, run an application linked against the
// 2.0 vesion of the SDK

// The way to handle this is to use what are called "Availability Macros". The pre-compiler macro
// __IPHONE_2_1 will be defined for SDK 2.1 and later, but not on SDK 2.0
#ifdef __IPHONE_2_1
cell = (CustomCell *)[nib objectAtIndex:0];
#else
cell = (CustomCell *)[nib objectAtIndex:1];
#endif

}
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.computers objectAtIndex:row];
cell.colorLabel.text = [rowData objectForKey:@"Color"];
cell.nameLabel.text = [rowData objectForKey:@"Name"];
return cell;
}
Chapter 8, Page 208: The return statement for

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

is missing its return value of kTableViewRowHeight or a hardcoded value of 66.

Unfortunately, I have the printed book instead of the PDF, and can not provide the PDF page number.
Page 208, bottom of page, method should be:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return kTbleViewRowHeight;
}
Chapter 4, page 85

Should viewDidLoad make a [super viewDidLoad]; call?
It's generally a good idea to do so, and we should probably add the call to the end of the method for the next printing of the book, but it's not strictly necessary in this case because we know that the superview (UIView) has an empty implementation of viewDidLoad:
Chapter 4 page 81 (PDF 107)

In the following method 'delegate:self' should be 'delegate:nil' in order to conform to the snippet on page 83 (PDF 109) and the discussion in the first paragraph of page 84 (PDF 110).

UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Something was done"
message:msg
delegate:self
cancelButtonTitle:@"Phew!"
otherButtonTitles:nil];
The code in the book is, in this case, correct. This class needs to get notified when the sheet is dismissed, which requires it to be the delegate. No change is needed to the code.
On page 127 of ebook, in the following segment of code:

if (self.blueViewController.view.superview == nil)
{
[yellowViewController.view removeFromSuperview];
[self.view insertSubview:blueViewController.view atIndex:0];\
}

The backslash after the semicolon should be removed.
Page 127 of printed book,

if (self.blueViewController.view.superview == nil)
{
[yellowViewController.view removeFromSuperview];
[self.view insertSubview:blueViewController.view atIndex:0];\
}


Should be

if (self.blueViewController.view.superview == nil)
{
[yellowViewController.view removeFromSuperview];
[self.view insertSubview:blueViewController.view atIndex:0];
}
Chapter 4 eBook version
pg 82 (pg 108 of pdf)

2nd paragraph, 3rd sentence reads:

More specifically, the delegate’s actionSheet:didDismissWithButtonIndex:actionSheet:didDismissWithButtonIndex:
method will be called.

but should read:

More specifically, the delegate’s actionSheet:didDismissWithButtonIndex:
method will be called.
The correct method name is just actionSheet:didDismissWithButtonIndex:
Ch 6, page 121 (PDF page 147)

In the code listing for SwitcherAppDelegate.h, there is a class declaration that has been struck through, with a correct version below it. Looks like the struck through line was not intended to be in the book, as it doesn't appear by default in my SwitcherAppDelegate.h file when I open it and so there's no need to remove it. I'm guessing the strike-through was an editing note for the book, rather than an instruction to the reader. I'm using iPhone SDK 2.2, by the way.

The struck-through line:
@class View_SwitcherViewController;

The (apparently) correct line below it, that needs to be added by the reader:
@class SwitchViewController;
The crossed-out line can be ignored; apparently Apple has removed the unnecessary line from the template.
Chapter 5 page 106 (132 of PDF)

- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {

In the method declaration, the 'UIInterfaceOrientation' is defined as 'toInterfaceOrientation', but in the rest of the code, it is referred to as 'toOrientation'. This causes an error on build.
Method declaration on page 106 (132 of PDF)

- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {

should be changed to

- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:
(UIInterfaceOrientation)toOrientation
duration:(NSTimeInterval)duration {