Skip to content

Book Review: Cocoa Design Patterns

Although I pointed out a minor mistake in the book in an earlier post, I highly recommend Erik M. Buck’s and Donald A. Yacktman’s Cocoa Design Patterns (released in late 2009) to every Cocoa programmer who has worked through one or more beginner books to Objective-C and the Cocoa framework.

Many ways to structure a book

Many books about Cocoa introduce the framework’s features by talking about one class (or a group of related classes) per chapter and creating a small sample application to show how a programmer would integrate this class into their own project. An example is Aaron Hillegass’s wildly popular Cocoa Programming for Mac OS X. After a general introduction to some of Cocoa’s key concepts, Hillegass mostly introduces specific features like NSUndoManager, window controllers, NSUserDefaults, table views, event handling etc. by explaining the class interfaces of these features and how to implement them. If a feature requires a further explanation how it works under the hood, this is worked into the flow of the chapter. This practical approach is a great way for programmers to learn how to use a framework like Cocoa (and Cooca Programming for Mac OS X is a very good book, everyone should read it). However, sometimes it can leave you a little in the dark about what is going on under the hood.

How does it work and why did they design it this way?

In contrast, Cocoa Design Patterns is built around the questions, How does it work and why did they design it this way?, with specific applications of the design patterns mentioned in the relevant places. Each chapter of the book is devoted to one specific design pattern and its implementation in Cocoa. This is especially beneficial because in Cocoa, many problems are solved a little differently than in other popular frameworks, partly due to the dynamic nature of Objective-C. The authors spend a great deal explaining the motivation behind both the patterns themselves and their implementation. If you have read the classic “Gang of Four” book on design patterns, you will recognize most of the patterns (even if they often have different names), and this book is a perfect addition.

Here are a few of the patterns discussed in the book that I found most helpful:

  • Model-View-Controller as the grand pattern that structures the entire framework.
  • Dynamic Creation of objects and the many places throughout the framework this feature of the Objective-C runtime is used, from scripting to unarchiving to plug-in architectures.
  • The ever-present Delegate pattern.
  • The target-action mechanism.
  • Invocations and their role in the undo/redo process.
  • The Flyweight pattern and how it is employed by NSNumber and NSCell to save memory and performance.
  • Proxies and Forwarding and how this can be used to implement Higher Order Messaging.

The book is a little Mac-centric in that it does not specifically talk about the iPhone and some of the examples mentioned only apply to the Mac. That part is small, though, and I would say Cocoa Design Patterns is equally useful to iPhone developers. Again, highly recommended for intermediate Cocoa developers.

CHDataStructures on the iPhone

With NSArray, NSDictionary, NSSet and their subclasses, the Foundation framework provides a number of basic collection classes. If you need more specialized or advanced collection data structures, there is a good chance that Quinn Taylor’s CHDataStructures framework already has what you need. CHDataStructures is open source under a very liberal license and well-tested. It includes collection classes for different types of trees, specialized dictionaries and sets, linked lists, and many more.

I recently helped Quinn to make the CHDataStructures project iPhone-compatible. You can now grab the latest version from the repository and either build a static library to include in your iPhone projects or add the entire code to your project. The readme file includes detailed installation instructions.

Even though CHDataStructures included virtually no OS X-specific code, we had to tweak the build configuration to make it work on the iPhone as seamlessly as possible:

  • Unfortunately, Apple does not support frameworks (so useful!) or dynamic libraries on the iPhone, so we have to build a static libary (or include all the code directly in our iPhone projects). And since we are dealing with two different architectures (ARMv6 on the iPhone and i386 on the iPhone Simulator), we actually need to build different versions of the static library.
  • Unit Testing in Xcode means that the tests are run from a script during the build phase and test results show up in Xcode’s Build Results window. This is great if you are developing for the same platform your development system runs on, which is usually the case (or close enough) if you write OS X apps. If you develop for the iPhone, your build runs on an Intel machine but you want your unit tests run against the ARM architecture. To accomplish this, you need a separate iPhone unit testing app that installs on the device, runs all unit tests upon launch, outputs the results to the console, and quits. Apple has a good how-to on this.

I highly recommend CHDataStructures to anyone who needs more than the standard collection classes.

Mutable Properties of Immutable Objects

Objects are called immutable if their state cannot be changed after initialization. While less flexible than their mutable counterparts, immutable objects have a lot of advantages. For instance, callers of a method that takes an immutable object as a parameter need not fear that the method might change the object. Also, thread safety is much easier to ensure if the objects shared by multiple threads are immutable.

For these and other reasons, it is often a good idea to make your own custom classes immutable, too. If you do so, it is important that all properties of your class also return immutable objects. I found an example of what not to do in the otherwise excellent book Cocoa Design Patterns by Erik M. Buck and Donald A. Yacktman: on page 144, they define a class that has a read-only property returning an NSMutableDictionary:

@interface WordInformation : NSObject
{
    // ...
    NSMutableDictionary *puzzleSpecificAttributes;
}
// ...
@property (readonly, copy) NSMutableDictionary *puzzleSpecificAttributes;
 
@end

This totally defies the purpose of immutability. Even though the property itself is read-only, users of the class are free to modify the mutable dictionary that is returned by the class’s getter. If your class relies internally on the dictionary not being changed, things can get really ugly.

How do we avoid this? The public-facing property must be an NSDictionary:

@property (readonly) NSDictionary *puzzleSpecificAttributes;

But chances are that, internally, you would still like to keep the mutable dictionary. In that case, rename the instance variable so that it does not conflict with the name of the read-only property and, in the implementation of your class, write a custom getter that converts the mutable to an immutable dictionary:

@implementation WordInformation
 
@dynamic puzzleSpecificAttributes;
 
// ...
 
- (NSDictionary *)puzzleSpecificAttributes {
    // mutablePuzzleSpecificAttributes is the mutable instance variable
    return [NSDictionary dictionaryWithDictionary:mutablePuzzleSpecificAttributes];
}
 
// ...
@end

OBShapedButton: Non-rectangular buttons on the iPhone

UIButton has always been capable of displaying buttons with arbitrary non-rectangular shapes. All you have to do is use PNG images with alpha channels to define the transparent parts of the bounds rectangle.

While a button’s shape may be arbitrary, UIButton always responds to touches within its entire bounds, however. This could cause problems and confusion for the users, especially when multiple non-rectangular buttons are placed close together so that their frames overlap.

OBShapedButton is a replacement for UIButton that solves this issue. Instances of OBShapedButton only respond to touches where the button image is non-transparent. Here’s how to use it:

  • Get the code from GitHub.
  • Add OBShapedButton.h, OBShapedButton.m, UIImage+ColorAtPixel.h, and UIImage+ColorAtPixel.m to your Xcode project.
  • Design your UI in Interface Builder with UIButtons as usual. Set the Button type to Custom and provide transparent PNG images for the different control states as needed.
  • In the Identity Inspector in Interface Builder, set the Class of the button to OBShapedButton.

That’s it! Build and run the enclosed demo project to check it out. I am releasing this under the MIT license.

The Apple Symbols font: a great repository for iPhone button icons

For iPhone developers looking for icons to use in buttons, toolbars, navigation bars and tab bars, there are a few good resources available, for example Joseph Wain’s excellent (and free!) collection of 130 icons and Eddie Wilson’s set of 160 iPhone UI icons ($69). These are not only beautifully designed but also already have the right sizes and format for use in toolbars and tab bars.

If you are not afraid of making your own PNGs, there is another free and hidden treasure in every Mac OS X installation: the Apple Symbols font. It contains many of the icons Apple uses in the built-in iPhone apps and makes them readily available for your own buttons.

Background: standard buttons in the iPhone SDK

The set of standard buttons that Apple ships with the iPhone SDK is quite limited in both number and context. For instance, the standard toolbar buttons can only be used inside a UIBarButtonItem on a toolbar or navigation bar. Now, this is a good thing, I hear you say, because it enforces consistent UIs. And I agree to a point. Specifically, I urge you to follow Apple’s Human Interface Guidelines and use the system-provided buttons for (and only for) their documented meanings or you risk the rejection of your app.

Icons for buttons, toolbars/navigation bars and tab bars shipped with the iPhone SDK

Icons for buttons, toolbars/navigation bars and tab bars shipped with the iPhone SDK

Apple Symbols to the rescue

If the standard buttons do not cover your needs or ff you need to use one of the standard toolbar buttons outside of a toolbar (in a simple UIButton, for example), you are out of luck. But Apple Symbols contains many more standard icons for your icon-making pleasure. Open the OS X Character Viewer in Glyph View, select the Apple Symbols font and scroll down to the very end of the Glyph Catalog:

The Apple Symbols font in Character Viewer

The Apple Symbols font in Character Viewer

Making a button from one of these glyphs is as simple as inserting it into Photoshop or any other graphics software that can work with fonts, resizing it, and saving it as a transparent PNG. Use about 20⨉20 pixels for toolbar and navbar icons, and about 30⨉30 pixels for tab bar icons and other buttons.

Am I allowed to do this?

I am not a lawyer but I have not found any restrictions that would forbid the use of these glyphs in your apps. This is what the Mac OS X license agreement has to say about fonts:

D. Fonts. Subject to the terms and conditions of this License, you may use the fonts included with the Apple Software to display and print content while running the Apple Software; however, you may only embed fonts in content if that is permitted by the embedding restrictions accompanying the font in question. These embedding restrictions can be found in the Font Book/Preview/Show Font Info panel.

And Font Book lists no license or embedding restrictions for Apple Symbols:

Apple Symbols Font Info

Updated iTunes Connect Financial Reports to HTML script

A user of my iTunes Connect Financial Reports to HTML script notified me that the script did not work on the file format that Apple used for their Financial Reports until January, 2009. The fix was relatively simple so the new version should support both formats.

I used the occasion for a few more changes:

  • I renamed the script to itunesconnect2html.rb.
  • I moved the HTML template to a separate file (instead of inlining the HTML code in the script), which makes the HTML much easier to customize and the code a lot cleaner. Win-win! ERB connects the two.
  • Added a README.txt with some documentation.
  • Fixed a bug that caused a crash when calling the script from another folder.
  • Moved the whole thing to GitHub.

Please get the updated code from GitHub. I’d appreciate your feedback and/or bug reports.

Managing the Network Activity Indicator

iPhone developers should use the little network activity indicator in the iPhone’s status bar to inform the user when their app accesses the network. Showing or hiding the indicator is simple:

[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

Most people probably call this method from their view controllers. This works fine until you have to deal with multiple concurrent tasks that access the network and/or multiple view controllers that are active simultaneously. For example, you might be running a HTTP request to download data from a webservice in the background and using a MKMapView instance that accesses the network whenever the user moves the map to a new location.

If you access the networkActivityIndicatorVisible property directly from multiple methods in these cases, chances are that you hide the indicator when the first task has finished even though your app continues to access the network. You would need to implement a counter to remember how often the network activity indicator has been shown and hidden to manage it correctly. If your code is spread among multiple view controllers, this gets even more cumbersome.

This “problem” is admittedly a small aspect of usability but the solution is so simple and elegant that I think it is worth doing even if you do not deal with multiple concurrent network activity tasks in your app.

Since the network activity indicator is displayed outside of your app’s window, the logical place to manage it is not a view controller but the application delegate. I have written a short method in my app delegate that uses a static variable to keep track of the number of times the activity indicator was asked to show or hide:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)setNetworkActivityIndicatorVisible:(BOOL)setVisible {
    static NSInteger NumberOfCallsToSetVisible = 0;
    if (setVisible) 
        NumberOfCallsToSetVisible++;
    else 
        NumberOfCallsToSetVisible--;
 
    // The assertion helps to find programmer errors in activity indicator management.
    // Since a negative NumberOfCallsToSetVisible is not a fatal error, 
    // it should probably be removed from production code.
    NSAssert(NumberOfCallsToSetVisible >= 0, @"Network Activity Indicator was asked to hide more often than shown");
 
    // Display the indicator as long as our static counter is > 0.
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:(NumberOfCallsToSetVisible > 0)];
}

This method alone is then responsible for the actual call to the UIApplication instance to show or hide the indicator. All view controllers call the method on the app delegate instead:

[(MyAppDelegate *)[[UIApplication sharedApplication] delegate] setNetworkActivityIndicatorVisible:YES];

Formatting iTunes Connect Financial Reports

Update 2009-09-23: There is an updated version of the script available. Please see the corresponding blog post and get the newest version of the code from GitHub.

The monthly financial reports Apple provides to iPhone developers in iTunes Connect are plain tab-separated text files. To print those reports for our tax accountants or the taxman, we must apply a little formatting. Since importing text files into a spreadsheet involves some manual work (some columns have to be marked as numeric or text) and I do not need to do further calculations with the data at the moment, I wrote a Ruby script that converts Apple’s text files into printable HTML tables.

To use the script, download all financial reports from iTunes Connect into a folder and run the script as follows:

./financialreport_to_html.rb *.txt

The script will create a .html file with the same name for every file you specify on the command line. You can use the -o option to force it to overwrite existing files.

The script uses a settings file in YAML format to configure things like column headings, column types and which columns to exclude from the formatted page (there’s a lot of columns to fit on one page). Have a look at financialreport_to_html_settings.yaml to see the available options.

The HTML template code, complete with CSS, is directly embedded in the script file. I opted for a simple table that looks good when printed but it should be easy for you to adapt the styling to your needs. The only thing you still have to do manually is to set your printer to landscape format as the page orientation cannot be specified in CSS.

The result looks like this:

Output from financialreport_to_html.rb

Output from financialreport_to_html.rb

Download the script: financialreport_to_html.zipGet the newest version from GitHub. You can do whatever you want with it. I hope you find it useful.

Songtext stopped working

Songtext displaying error message

Songtext displaying error message

As of this morning, Songtext is no longer working. LyricWiki, the site Songtext obtained its lyrics from, was required by music publishers to cripple their API in such a way that apps like Songtext no longer have direct access to the lyrics. This effecticely breaks Songtext and many other iPhone lyrics apps that also used LyricWiki as their source.

I am very sorry to all users but at the moment there is nothing I (or LyricWiki) can do about this.

I would like to thank the guys at LyricWiki for their efforts in providing an API in the first place. And special thanks for providing users of Songtext and other apps with a clear error message that should minimize support requests for app developers:

Unfortunately, due to licensing restrictions from some of the major music publishers we can no longer return lyrics through the LyricWiki API (where this application gets some or all of its lyrics).

The lyrics for this song can be found at the following URL: …

(Please note: this is not the fault of the developer who created this application, but is a restriction imposed by music publishers themselves.)

I sincerely hope that the music publishers are working on a solution that would allow for the existence of lyrics apps in the future. The popularity of some of these apps clearly shows that there is a demand. Instead of only crippling third-party solutions, they should provide their own APIs (with their own licensing model if they feel they need to be compensated).

I removed Songtext from the App Store

As of today, Songtext is no longer available as I just removed it from the App Store.

Unfortunately, this also means that there will be no updates for existing users in the foreseeable future. Sorry.

I want to thank everybody who has downloaded Songtext in the last 2 weeks for your support and positive feedback. I hope you still enjoy using the app.