By Developers, For Developers

Historical errata for iOS Recipes

PDF PgPaper PgTypeDescriptionFixed onComments
159ERROR

Line wrapping wrong in the last paragraph (-prp_stringByAddingPercentEscapesUsin)

2011-05-02
1TYPO

Not really a PDF problem per se, but I had to provide a page number to get past the web form :-)

When reading the ebook on the iPad, much of the table of contents is empty. Line numbers are given, but those line numbers have no titles to tell you what’s on that page.

Through experimentation it appears that they are the headers for the different recipes. I suspect this is related to a problem where the headers of the recipes appear in body text instead of some kind of header style.

2011-03-16This has been fixed now. Re-download from your accounts page. \n \nFYI..I needed to delete my current copy to get it to show the changes.
169ERROR

web server for MultipartHTTPPost doesn’t seem to accept files neither using the web form nor in iphone project. i get the following error:
“undefined method `filename’ for nil:NilClass”

2011-03-10Thank you; looks like this was a bad commit. It'll be fixed in the next beta.
162OK

can you provide a rails app with any popular gem such as paperclip or carrierwave to handle the upload instead of the webrick server. you would make my life and other’s much easier.

2011-03-10We chose WEBrick because comes with Mac OS X and the server script is fairly simple. The recipe itself has been tested with many Rails, PHP, Java-based servers. If it doesn't work with your server setup, please let us know ASAP.
15ERROR

Working my way through the book. Anyway -

The implementation of -[PRPSplashScreenViewController viewDidLoad] should assign the contentsScale property of the layer. As it is, if Default.png@2x is used, the scale of the CGImage will be 2.0, but the contentsScale of the view controller’s view layer will be 1.0. This results in a layer rendered at twice the scale of what it should be when the splash screen’s view is shown on high dpi devices and an @2x image is available.

// Good
- (void)viewDidLoad {
self.view.layer.contents = (id)self.splashImage.CGImage;
self.view.layer.contentsScale = self.splashImage.scale;
self.view.contentMode = UIViewContentModeBottom;
}

// Bad
- (void)viewDidLoad {
self.view.layer.contents = (id)self.splashImage.CGImage;
self.view.contentMode = UIViewContentModeBottom;
}

2011-03-14This code predates Retina, and I've since learned the lesson. Ported to use UIImageView in hopes of insulating against future OS changes.
16ERROR

After going to all the trouble of defining a delegate protocol and implementation, it would probably be a good idea to set the app delegate as the splash screen controller’s delegate.

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window addSubview:self.navController.view];

splashController = [[PRPSplashScreenViewController alloc] init];
// Good
splashController.delegate = self;
[self.splashController showInWindow:window];

[self.window makeKeyAndVisible];

return YES;
}

2011-03-14This actually isn't necessary for the sample; the delegate methods are optional, and provided as a convenience in case you need to take action when the transition is complete. We'll clarify this in the chapter text and/or think of an example of "action." \n \n-- (Update) The sample does use the delegate methods to release its splashController, so we'll make the suggested change. Thanks Allen.
91TYPO

In -viewDidLoad, you’re missing the sentinel nil for arrayWithObjects:

2011-03-10Thanks; luckily that's the "what not to do" example :-)
1SUGGEST

“in the excerpt ”Tame the Network Activity Indicator“, you don’t mention anywhere in the text that the state is saved in a global, static variable. In my eyes, this is essential for understanding the code. To improve understanding, I think you could add a sentence or two explaining the static global variable…”

2011-04-13
168TYPO

multipart POST request doesn’t work with my rails set up; the response returns null and the data length is zero!.
Posing through the web form works just fine though.
I’m using carrierwave gem to handle the uploads.

2011-03-22Can you bring this to the forums at http://forums.pragprog.com/forums/151 \n \nI'd like to go into more detail with you. Thanks.
81TYPO

Method on the bottom of page should probably look like this:
- (IBAction)cellButtonTapped:(id)sender { NSIndexPath *pathForButton =
[self.tableView prp_indexPathForRowContainingView:sender]; // difference in prp_ prefix
}

2011-03-12Yes it should. Nice catch, thanks.
57SUGGEST

the custom setter of setAttributedText should probably compare the pointer being passed in to the ivar. releasing the ivar before doing so could result in that object being dealloc’d.

2011-04-06Thanks Paul. Now fixed.
151ERROR

This sentence repeats prp_pushNetworkActivity twice, the second one should be prp_popNetworkActivity:

Just call -prp_pushNetworkActivity whenever starting a connection, and -prp_pushNetworkActivity whenever the connection terminates.

2011-03-12
11ERROR

splash screen reveal : compilation failed error - there is no SDK with the name or path ‘iphoneos’.
i am using xcode 3.2.2(1650) and iphone SDK 3.2

please advise else not able to proceed.

thanks :-)

2011-03-13This is discussed here: http://forums.pragprog.com/forums/151/topics/8780 \n \nJust change the project build settings to "Latest iOS" and reopen the project. Fixed in the next beta.
89SUGGEST

This is about custom-Nib cells. If the tableview you are using is part of a larger view that gets dynamically loaded from a xib, the viewDidLoad method does not get called. In those cases, you can put “self.complexCellNib = [PRPComplexTableViewCell nib]” in the “initWithNibName” method of the main view.

2011-03-13Thanks Brett. I converted it to a lazy initializer (custom getter) which should account for any use case.
16OK

in the last code snippet on the page:
splashController = [[PRPSplashScreenViewController alloc] init];

should be:

PRPSplashScreenViewController splashController = [[PRPSplashScreenViewController alloc] init];

2011-03-14It's assigning an ivar intentionally; I've clarified this in the text.
15ERROR

Shouldn’t you also make a call to super inside your override of viewDidLoad?
[super viewDidLoad];

2011-03-14We're now using an image view via -loadView, which obsoletes this issue.
31OK

LOVE the book! Just added PRPToggleButton to a project - one created via a nib and one created in code. The one created in code works as advertised, but the one from nib doesn’t toggle its background image. Interestingly enough, I know (through PRPDebug!) that the “on” boolean IS changing back and forth between 0 and 1 - but the “on” background image never displays, only the off and highlighted images. Wondering if something additional needs to happen in awakeFromNib?

2011-03-29Let's discuss this on the Forums: \n \nhttp://forums.pragprog.com/forums/151/topics/8795
182TYPO

I believe the setUsername:(NSString *)username method listed at the top of page should be named prp_setUsername

2011-03-17
181SUGGEST

When talking about determining if a key exists in user preferences, why not mention the defaults capability available in NSUserDefaults using the registerDefaults: method of NSUserDefaults.

2011-03-20This is a good suggestion; the intent was to "not need" -registerDefaults but the recipe should supplement the API, not replace it. We'll add some text in the next beta.
183TYPO

The @property declaration for prp_username is missing the getter=prp_username attribute.

2011-03-17
14SUGGEST

The “Add a Basic Splash Screen Transition” recipe could be generalized for the iPad (which has a different “default.png”), which also includes different launch orientations.

2011-04-06
15SUGGEST

I’d like to echo comment #46588.
I would like to see this recipe (#1) expanded to handle not just Default.png, but also:
Default-Portrait.png \t768w x 1004h
Default-PortraitUpsideDown.png \t768w x 1004h
Default-Landscape.png \t1024w x 748h
Default-LandscapeLeft.png \t1024w x 748h
Default-LandscapeRight.png \t1024w x 748h

And retina (@2x) options as well.

Would just make this recipe 100% complete/whole. Thx.

2011-04-06
24ERROR

When first discussing the “Animate a Custom Notification View” Problem in Recipe 3, UIActionSheet is mentioned as a notification mechanism; UIAlertView seems like the better class to use to present information to the user.

A UIActionSheet seems more like you’re demanding information from the user before you can continue, rather than trying to present them with a message and a reason why they have that notification.

2011-04-06Agreed. I'll make the change.
0SUGGEST

I am little bit surprised that the book does not cover any scenarios that deal with multi threading (beside the file upload example). For example how one would prevent user input while in the background data from a web service is loaded asynchronously. Or like creating a modal dialog which blocks the code execution etc. I am using CFRunloopRun() but encounter various shortcomings with it like that if one is not careful I run into multiple execution of it (which ended up in a deadlock) or that UI events are not consumed but queued so that multiple clicks still are executed afterwards.

150TYPO

In the second line of the solution part:
network l“spinnerr”

2011-03-22
17OK

In the second line of performTransition, you use a class called PRPSplashScreenFadeAnimation, which doesn’t exist:

(void)performTransition { [UIView beginAnimations:PRPSplashScreenFadeAnimation context:nil];

2011-04-06It's actually a string constant defined at the top of the same .m file. If you're having compilation issues, please post to the Forums and we can help you out. \n \nThis code is receiving an overhaul in light of 4.x changes; we wanted to get the changes into B2 but ran out of time. Stay tuned.
17ERROR

Recipe #1 will not allow the actual App UI to properly respond to orientation changes. If the user were to turn the device, the splash screen will track the orientation changes, but because iOS only supports one active view controller, the App UI will be stuck in Portrait orientation until its view controller becomes the active one (once the splash screen’s view is removed from the window).

This is much more important in the iPad than the iPhone, since the iPad is expected to support all orientations, and is more likely to be reoriented by the user depending on the App.

Possibly a better solution is to implement the splash screen as a custom view added to the App’s main view controller so orientation changes can be supported both by the splash view and the UI’s view hierarchy.

2011-04-06
112SUGGEST

In the method addNonScalingSubview:(UIView *), it is not necessary to call the NS[Mutable]Set containsObject: before adding the view to the nonScalingSubviews container. A NS[Mutable]Set is an unordered set of distinct objects, so adding an object it already contains would have no effect (unlike a NS[Mutable]Array for instance).

It can be presumed that the NSMutableSet’s addObject: method already calls containsObject: before determining whether to add the object, so the code in addNonScalingSubview:(UIView *) is essentially asking the set to search twice for each view it doesn’t already contain before adding it.

2011-03-29Thank you Scott; it started life as an array but I changed it to an NSMutableSet later and forgot to take this out.
78ERROR

I think you’re leaking an instance of AVAudioPlayer on line 69 of PRPScrollingTextViewController.m

I only mention this because I’ve found that how you release AVAudioPlayer instances is important.

2011-04-06Thanks Taran. Good catch. Leak Plugged.
33SUGGEST

Just a note about the sample code from the website.

The file “highlighted.png” referenced in ToggleButtonViewController.m does not seem to be present in the project. Not sure if this is what the #warning in the source file is referencing.

2011-04-14
42TYPO

Obvious typo:

“To get the most out of them, however, we need to understand how stretchable UIImagesUImages work.”

UIImagesUImages should be UIImages.

Language in the first two paragraphs of the solution feels a bit awkward and repetitive too IMHO.

2011-04-06Thanks Allen. I've fixed the typo and I'll work on the wording in the next beta.
36SUGGEST

It could help clarity if the labelA was omitted or moved to the preceding code snippet, since the snippet it is in doesn’t do anything with it and is focused on the setup of a UIView with UILabel.

17SUGGEST

This book is making my life a lot easier. Thank you for writing it!

On page 17 the code sample for BasicSplashScreen/PRPSpashScreenViewController.m demonstrates UIView’s static beginAnimations:context: method. The Xcode documentation for this method says it is “discouraged in iOS 4.0 and later. You should use the block-based animation methods to specify your animations instead.”

Do you plan to update this example to use UIView’s animateWithDuration:animations: (inter alia) instance methods?

Thanks again.

2011-04-06
174TYPO

A space is missing in NSMutableDictionaryproperty.
Should be NSMutableDictionary property.

2011-04-04
173TYPO

Formatting Error for the RFC URL in paragraph 2 under “Solution”.

2011-04-04
87SUGGEST

Recipe 15 has no links for downloading the .h files.

2011-05-02Jonathan, All download files are available from the Book page under the Book Image, marked as Code
190ERROR

Setting “Other C flags” did not work for defining DEBUG, but adding that value to “Preprocessor Macros” did.

2011-04-06You need a -D prefix for Other C Flags. Beta 3 clarifies this better and includes a screenshot from Xcode 4.
108OK

You are sending an indexPathForRowContainingView: message to UITableView. On page 107 the method was implemented with a prp_ prefix.

2011-04-06I believe this was fixed in Beta 2. Please elaborate in the forums if it's still a problem in Beta 3.
21TYPO

on the top:
NSLog(@“Rorate”);

2011-04-07Thanks, that should have been removed :-)
80SUGGEST

hi paul,

i have been very much enjoying your new book. getting in on the beta level is great. you’ve given me some great code to chew on!

i am a newbie, not worthy to lace the strings of your in-line skates…may i humbly submit…

in chapter 13 “having fun with auto-scrolling text” on page 80, you use this animation in viewDidAppear

//
// ScrollingCreditsViewController.m
// ScrollingCredits
//
// Created by Paul Warren on 11/24/09.
// Copyright Primitive Dog Software 2009. All rights reserved.
//

-(void)viewDidAppear:(BOOL)animated {
\t
\t//START:Animate
\t[UIView beginAnimations:"scroll" context:nil]; \t[UIView setAnimationDuration:35]; \t[UIView setAnimationCurve:UIViewAnimationCurveLinear]; \t[self.textView setContentOffset:CGPointMake(0, 500) animated:NO]; \t[UIView commitAnimations]; \t//END:Animate \t \t//START:Audio \tNSURL *url = [NSURL fileURLWithPath: \t\t\t\t [NSString stringWithFormat:“%@/HeliumWars.m4a”,
\t\t\t\t [[NSBundle mainBundle] resourcePath]]];
\t
\tNSError *error;
\taudioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:url error:&error];
\taudioPlayer.numberOfLoops = 1;
\t[audioPlayer play];
\t//END:Audio
}

in iOS4, the apple documentation now is steering us to use block-based animation instead. this is all new since your wrote your code in 2009. since you’ll be published in 2011, might you also wish to code this using blocks?

humbly submitted,

don delwood
ddelwood@mac.com

2011-04-12Thanks Don, glad your enjoying the book. Of course, you are right, about the code that is, not my in-line skates :) I'll make the change before the next release.
209SUGGEST

source files UIView+PRPSubviewTraversal.h/.m have “UIView+SubviewTraversal.h” and .m in the comment at the top of the file. Ideally it’d have the actual file name as this would make copying and pasting it into an #import statement much easier.

thanks.

2011-04-12
21SUGGEST

The throw-away line “The splashScreen property referenced above is connected to the app del- egate in Interface Builder, rather than in the code.” is so vital, it would make sense to expand on this, and walk through how it’s done. Without, the project won’t work.

2011-04-15
15ERROR

If you are making this universal, and you add different title screens for iPad, iPhone 3G and iPhone Retina (and make them all different looking images so you can tell) the app will DOUBLE the retina image after the first transition. I just started playing with this so I’m not sure where the error actually lies.

2011-04-25Keith. Recipe 1 is already Universal with the latest batch of code updates, as it's using a different technique now. Recipe 2 has been updated to complete the universal code and to add support for various device scales, such as Retina. \n \nI'm not sure yet when the new code will be uploaded so the two main components are: Using [Uimage imagenamed:@Default.png] to create the image will pull in the correct Default for iPad and Retina variants. Adjusting the Layer scalefactor to match the screen resolves the issue of the oversized iPad image. \nself.view.layer.contentsScale = [[UIScreen mainScreen] scale]; \n
34SUGGEST

Hi Matt,

First, congrats and thanks for this book! Amazing resource!

In the 4th recipe (Create Reusable Toggle Buttons), in the buttonWithOnImage:offImage:highlightedImage: you call ‘[PRPToggleButton buttonWithType:UIButtonTypeCustom]’.

Wouldn’t it be interesting to call ‘[self buttonWithType:UIButtonTypeCustom]’ for easy subclassing?
I’d be interested to read your feedback!

Thanks again,
Thomas.

2011-04-29Good call, Thomas. I've made the change.
275ERROR

The PRPConnection class declares a urlRequest property but does not retain it

- (id)initWithRequest:(NSURLRequest *)request
progressBlock:(PRPConnectionProgressBlock)progress
completionBlock:(PRPConnectionCompletionBlock)completion {
if (self = [super init]) {
self.connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO] autorelease];
self.progressBlock = progress;
self.completionBlock = completion;
self.url = [request URL];
self.progressThreshold = 1.0;
}
return self;
}

2011-05-02
121TYPO

UIMapView should be MKMapView

2011-05-02
96-97ERROR

You are creating the UITableViewCell subclass like so:

cell = [[[self alloc] initWithCellIdentifier:cellID] autorelease];

Unless you’re using an SDK release from a time other than 2011 (you’re from the future, aren’t you?), this does not look like a valid init method. Perhaps you meant:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

Which seems to be the most common initializer for UITableViewCells. Or perhaps you meant to write your own designated initializer by that name, but unfortunately I don’t see where that part is really mentioned.

2011-05-02Yes, this is a new designated initializer. I've clarified that point and included the relevant code snippet. Thanks for the input.
50SUGGEST

In the setAttributedText: method in coreText/Classes/PRPAttributedLabel.m wouldn’t it make sense to wrap the setter code in a [self willSetValueForKey:"attributedText"] and [self didSetValueForKey:“attributedText”] pair to let key/value observers know about the change? It may be a little out of scope, though, but generally seems like a good idea (just as you’re checking for pointer equality).

202TYPO

Recipe 39, the “infoxbox” “Use a Version Model” seems to contain some editing annotation that shouldn’t be there. First sentence of the 2nd paragraph:

“This recipe uses the more explicit The code tag should not be here. precisely because you may end up having more models in your bundle than you thought.”

201ERROR

The iOS recipe focuses on a generic Core Data initialization class. During the creation of the managed object model, the code calls the function (NSString *)modelName {} with a return value of [[NSBundle mainBundle] bundleIdentifier]. This provides the fully qualified bundle identifier for the iOS app (e.g. com.pragprog.BasicDataModel), but the managed object model is looking for the name of data model within XCode (which is typically the project or bundle display name - e.g. BasicDataModel) to be derived from. When the recipe is run the application will crash as the pathToModel function will return NULL as com.pragprog.BasicDataModel.momd is not a valid model name, but BasicDataModel.momd is valid. Recommend changing the model name to the full bundle identifier and making note of this subtlety in the verbiage within the recipe (or using a predicate regex and filtering out the “com.pragprog.” leaving the basic model name).

2011-05-17Yes, this was reported in the forums (http://forums.pragprog.com/forums/151/topics/9039) and I've made some changes to both text and code. Thank you.
7TYPO

Middle of page the Figure 3 description text is not shown under the figure.
After the Figure 3 label the word “accessed” is truncated to “cessed” with perhaps some other text missing? See copy of start of text below:

“Set the UIStatusBarHidden key to YES to hide the status bar on launch. If you want to show it in your main UI, set the splash screen’s showsStatusBarOnDis- missal property to YES
Figure 3—Hiding the status bar on launch
cessed anywhere in the code.”

16TYPO

The book web page URL has a trailing comma when you try to click on it or copy it.

Ends with
…/cdirec,
should be
…/cdirec

103ERROR

Recipe 20: Add Border Shadows for Table Views

After implementing the UITableView with border shadows, I noticed that the shadows behave incorrectly when the table view is manipulated, that is, when rows or sections are added, moved, or deleted. What happens is that the shadows stay in the same position as while the deleted row moves. The shadow moves to the correct position only after the animation of the moved cell is finished.

Is this a known issue? I think the authors provide an elegant solution for a table view with shadowed borders, but this downside makes it less appealing to actually use in an application.

2011-05-27Hi Bart, it's a known and conscious limitation. Long answer at http://forums.pragprog.com/forums/151/topics/9135
31ERROR

iOS Recipe: Reusable Web View Controller (SmartWebView XCode Project)

The (void)webViewDidFinishLoad:(UIWebView *)wv {…} method does not check to see whether the delegate responds to the associated protocol function webControllerDidFinishLoading: hence when the web view is instantiated within another class and the web view delegate is set to self the optional webControllerDidFinishLoading: protocol method will never be called if used.

Recommend adding: if ([self.delegate respondsToSelector:@selector(webControllerDidFinishLoading:)]) {…} else {…} logic to - (void)webViewDidFinishLoad:(UIWebView *)wv method in PRPWebViewController.m class.

2011-05-26
33ERROR

The webControllerDidFinishLoading:(PRPWebViewController *)controller method is never actually implemented in the code.

2011-05-26
xviSUGGEST

It would be useful, I think, if the subdirectories in the source-code download had their chapter/recipe numbers prefixed.

191TYPO

The defaults are loaded from a property list—DefaultPrefs.plist—bundled inside the app.

NSString *prefs = [[NSBundle mainBundle] pathForResource:"Prefs" ofType:“plist”];

Should it be…?
NSString *prefs = [[NSBundle mainBundle] pathForResource:"DefaultPrefs" ofType:“plist”];

The file I see in the latest project is called Prefs.plist, so it should add up OK. Can you confirm that you have the latest code from http://pragprog.com/titles/cdirec/source_code \n \n? Thanks. Please post to the Forums with more questions. \n \n
NAERROR

XCode Project: OrganizedTableView
iOS Recipes PDF: B5 (no page number as source is not contained in the book)

Within the PRPSwitchSettingsCell.m file, - (id)initWithCellIdentifier:(NSString *)cellID method, the self.selectionStyle property is assigned twice. Recommend removing either the first or last property assignment.

5TYPO

The link to the forum for discussion of the book is not found.

2011-12-28
97ERROR

Figure-19 is identified as “Reuse identifiers in Interface Builder” but there’s nothing obvious in that image about where to set them. This is on the wrong view for a table view cell object. It needs to be on the Attributes Inspector where Reuse Identifier is listed.

193TYPO

In the “Usa a Versioned Model” box at the top of the page, third sentence, the method name mergedModelFromBundles: is misspelled. It is missing the “l” in “Bundles”

198TYPO

In the second paragraph, first sentence, there is an extra word “do” at the end of the sentence. It should read, “Remember, categories do not let us declare storage on the class they extend; only methods.”.

97ERROR

The last line on the page reads:

cell.titleLabel.text = [NSString stringWithFormat:@“Cell #%d”, indexPath.row];

but it should probably read:

cell.textLabel.text = [NSString stringWithFormat:@“Cell #%d”, indexPath.row];

192TYPO

In the first paragraph of the “Solution” section, third sentence, you have reversed the order of two words “we that”. It should read, “… making sure that we support migration between model versions.”.

90ERROR

Looks like labelFrame is not defined in the sample code.

Categories: