Cocoa Trapa

Default Defaults

One of the first things I do on starting a new AppKit or UIKit project is add a few lines of code to set default values for NSUserDefaults. You’ll never have to check to see if nil was returned from a call to NSUserDefaults once you do this.Add the following snippet to your application delegate’s finished launching method.

1
2
3
4
5
6
     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
      NSURL *url = [[NSBundle mainBundle] URLForResource:@"DefaultDefaults"
          withExtension:@"plist"];
      NSDictionary *d = [NSDictionary dictionaryWithContentsOfURL:url];
      if (d)
          [defaults registerDefaults:d];

Then create a property list called “DefaultDefaults.plist” and add it as a resource. Anytime you add another preference/default to your application, add the default value to this plist.

Helpful Category for Debugging CALayer Issues

Having problems with layers not doing what you want? Give this category a try. Just import the header and add a call like NSLog(@"%@", [layer debugLayerTree]) and you’ll get a nicely formatted view of the layer tree including layer name, frame, and zPosition.

UINavigationController Doesn’t Call viewWillAppear or viewWillDisappear

When a viewcontroller is pushed or popped on to the UINvagiationController’s stack, viewWillAppear:, viewDidAppear:, viewWillDisappear:, and viewDidDisappear: are not called. Personally, I think this is biggest bug/design flaw I’ve seen on iOS or even MacOS X.

The navigation controller’s delegate receives willShow and didShow messages, so you can implement those and call viewWillAppear and viewDidAppear on the view controller given to that delegate method. But there is no obvious way to send the disappear messages, as the previous viewController has already been removed from the view controller stack (on a pop).

Here is a solution to the problem.

Sharing Code Between Mac and iOS Apps

Sharing code between Mac and iOS applications is easy for model classes, but trickier for controller classes (and not worth the effort for view classes). This post describes the design patterns and implementation we used in sharing code for our Music Trivia Party game.

Linking Doxygen-Generated Docs to Apple’s Docs

Doxygen is a fantastic documentation generator with support for Objective-C. However, it will only link to external objects and methods if supply a tag file, which would be pretty exhausting to write by hand for every property and method of every object in Cocoa.

Fortunately for you, I’ve done the hard work. I wrote a program that uses WebKit and parses locally installed Cocoa API documentation and generates the tag files for Foundation, AppKit, and COreData linking them to Apple’s website. (Apple’s developer license prohibits spidering their website, so I’m spidering the local copy and then computing what the Apple URL would be.)

Doxygen tag files for AppKit, Foundation, and CoreData

Binding Enabled to an NSArrayController

Enabled binding settings

Say you have a window with an NSTableView bound to an NSArrayController. You also have a button, say an OK button, that should only be enabled if a row is selected in the table. How do you do this?

AppKit does some secret jiggering behind the scenes and if the table view is not a subclass, it binds the selectionIndex of the table view to the array controller. So to link the enabled button, you’d bind to the key path selectedObjects.@count.

countForFetchRequest: Raises “Entity Not Found”

It appears there is a bug or undocumented “feature” in NSManagedObjectContext’s countForFetchRequest: method. I was using it without a problem, and then added multiple configurations to my application, splitting the data into multiple stores. I then got an exception with a reason of “entity not found” when I called countForFetchRequest:.