Tag Archives: Objective-C

isKindOfClass and XCTest

I learned something very useful today.  My group uses Apple’s XCTest as a framework for test automation.  Because of the way XCTest gets associated with the app, there are certain rules you need to follow that aren’t completely obvious in order to use certain very common features of CocoaTouch.

How XCTest Can Test Your App

When you create a test target to test your app, a separate executable image is built that doesn’t include the components of your app.  When you run a test, your app is run and then the test image is injected into the app process.  The result is that type information comparisons (e.g. isKindOfClass:) only work if the class objects are in the same image.

Fixing Type Comparisons

In order to compare types reliably, you must not include the same source files in both the app target and the test target.  If your project is small, this is a relatively simple task.  However, as your project gets larger and you start using CocoaPods or include libraries in other ways, you need to get a little more creative.

In our case, we use CocoaPods pretty extensively, and we build some of our code in libraries (and therefore separate pods) and some in the application.  The result is that I needed to create multiple pod targets to ensure that no source file was included in both targets.

Other XCTest Tidbits

I ran into this problem because I was building some tests with mocks and other tests without them, and the mocks were located in a separate pod.  In order to get my app to use the mocks, I created an app target that included the mocks directly.  Why, you might ask?  For the following reasons:

  1. My app view controller need access to the data that is being mocked before my tests are run.
  2. Setting a singleton value in a +load method doesn’t work because the +load method in the test target isn’t called
  3. Swizzling in the test target doesn’t work.

References

Double-Checked Locking and Objective-C

A common problem in software is to do something exactly once – e.g. create a singleton.  A corollary of that action is to do something exactly once in the life of an instance.  I have found myself using the corollary much more frequently as I move away from using singletons, which I’ve done to improve testability.

With singletons, a common solution is to use locking or, to avoid the performance penalty of locking, double-checked locking.  Of course, double-checked locking has issues with most modern languages caused by CPU and compiler instruction reordering.  Objective-C has provided an elegant solution to those problems, but the solution comes up a little bit short.

Creating a Singleton – Single-Threaded

In a single -threaded application, creating a singleton can be done without additional protection, like this:

+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
    if (s_sharedInstance == nil)
    {
        s_sharedInstance = [MyClass new];
    }

    return s_sharedInstance;
}

Creating a Singleton – Multi-Threaded

In a multi-threaded application, it’s not so simple as you will want to protect yourself against multiple callers of this method.  A simple solution simply adds a lock:

+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
    @synchronized(self)
    {
        if (s_sharedInstance == nil)
        {
            s_sharedInstance = [MyClass new];
        }
    }

    return s_sharedInstance;
}

The problem with this solution is that you pay the price of locking even though you only need it the first time the method is called.

Double-Checked Locking

A common solution to avoid the penalty of locking is to use double-checked locking.  With double-checked locking you check the value of the static instance both outside and inside the lock, like this:

+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
    if (s_sharedInstance == nil)
    {
        @synchronized(self)
        {
            if (s_sharedInstance == nil)
            {
                s_sharedInstance = [MyClass new];
            }
        }
    }

    return s_sharedInstance;
}

At first blush, it would seem that this would solve the problem of assigning the static variable AND avoiding the penalty of the lock.  The problem is that the CPU and/or the compiler could reorder the memory access instructions.  A solution suggested by Mike Ash inserts memory barriers before accessing the variable and uses the volatile keyword.  The memory barrier, available in libkern/OSAtomic.h, solves the CPU problem and the volatile keyword solves the compiler problem.

+ (MyClass *) sharedInstance
{
    static MyClass * volatile s_sharedInstance = nil;
    if (s_sharedInstance == nil)
    {
        @synchronized(self)
        {
            if (s_sharedInstance == nil)
            {
                OSMemoryBarrier();
                s_sharedInstance = [MyClass new];
            }
        }
    }

    OSMemoryBarrier();
    return s_sharedInstance;
}

The problem with this solution is that it is still quite expensive in the most common case.  Apple has provided another solution:  dispatch_once.

dispatch_once

dispatch_once is provided with Grand Central Dispatch to execute statements exactly once, like this:

+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        s_sharedInstance = [MyClass new];
    });

    return s_sharedInstance
}

This is a terrific solution for use with singletons, but what if you want to use it with an instance?  It actually happens to work, but Apple has a warning against using it in this way in the documentation for dispatch_once:

The predicate must point to a variable stored in global or static scope. The result of using a predicate with automatic or dynamic storage (including Objective-C instance variables) is undefined.

Hmm, that’s unfortunate.  Here’s hoping Apple will change their implementation.  In the meantime, it would appear that the only solutions for the non-static and non-global case are:

  1. Use a synchronized block for every call.
  2. Use memory barriers.

References

Sorting Objective C Import Directives

I know I’m a bit obsessive compulsive, but I’m rather fastidious about how I organize #import statements in alphabetical order at the top of my Objective C files.  If I’m creating and maintaining the file myself, it’s not so bad, but when I work on an existing file it’s a lot more work.  Wouldn’t it be cool if I could just run the sort command on the imports?

Automator to the rescue!  By creating a service in Automator, you can create a service that is accessible from Xcode – or any other app for that matter.

Check out this article by Christian Engvall that describes the steps required to make it happen.  Pretty cool!

ARC weak references on iOS 4

I’m finally exploring ARC (Automatic Reference Counting) for development on iOS 4 and above.  Mike Ash provides a terrific introduction to ARC along with some pitfalls.

One of the pitfalls of using ARC is that weak references (aka zeroing weak references) are not supported on iOS 4 or on Snow Leopard.  You could use Mike’s MKZeroingWeakRef class with all weak references, but now there is a better option:  PLWeakCompatibility.  This package allows you to use all the goodness of ARC weak references with the native syntax.  Brilliant!

You can even get PLWeakCompatibility on GitHub so you can keep up to date on its progress.

References:

Folding code in Xcode

A colleague of mine has the practice of collapsing all the methods in an Objective C file when he loads it to simplify finding the right method to view. When I asked him how he did it, he couldn’t remember since it was an automatic action. I finally got around to figuring out how to do it.

The feature is called Code Folding and can be done using the pointer, the menu bar, and the keyboard.

Code Folding using the Pointer

You may have noticed the different colored gray bars on the left of your code in Xcode and may have even accidentally hovered over one of them and been treated to a drastic change in the UI. Those gray bars allow you to fold – or collapse – your code. Using those bars, you can fold any size block, such as an if block, a for block, an @synchronized block, or even a whole method block.

Hovering over the gray bar shows you the block that will be folded. Clicking on the gray bar folds the block and shows a yellow ellipsis between the curly braces where the block used to be. It also changes the gray bar to an arrow. Clicking the arrow or double-clicking the ellipsis will unfold – or expand – the folded block.

Code Folding using the Menu Bar

The code folding functionality is exposed in the menus accessible from the menu bar as well.  In Xcode 4, check out Editor -> Code Folding.

Code Folding using the Keyboard

Apple has defined default keystrokes for code folding, but I found that some of them conflicted with keystrokes defined for other functions. In most cases the conflicts were caused by changes I had made – either in Xcode or in Mac OS X Lion – to accommodate writing code.

The following code folding functionality can be controlled using the keyboard:

  1. Fold all methods and functions – Option + Cmd + Shift + Left Arrow
  2. Unfold all methods and functions – Option + Cmd + Shift + Right Arrow
  3. Fold the current block – Option + Cmd + Left Arrow
  4. Unfold the current block – Option + Cmd + Right Arrow

I had to change the fold/unfold block key bindings because they conflicted with the key bindings I had selected for switching between Spaces in Lion. I changed them to Ctrl + Cmd + Shift + Left Arrow/Right Arrow respectively. This, of course, required that I change another key binding in Xcode – the key bindings for fold/unfold comment blocks.

Comment blocks are blocks of comments using /* and */ as delimiters. Since I almost never use this style of commenting, removing the key binding for folding/unfolding comment blocks in favor of code folding/unfolding was a good trade-off for me.

Defensive Programming in Cocoa (from VTM_iPhone)

I’ve been attending the iPhone Developers Conference in Seattle hosted by Voices That Matter (check out VTM_iPhone for the Twitter stream), which has been really informative.  Easily the most informative session at the iPhone Developers Conference for me was Defensive Programming in Cocoa by Mike Ash.  On Mike’s blog he has a series called Friday Q&A and it appears that most of the material for his talk was taken from an article he posted in December with the same name.  Two sections really stand out for me.

Memory Management – Put all your memory management for member variables in the setter for that member variable rather than scattering it around the code.  So instead of doing this:

[_myMemberVar release];

do this:

self.myMemberVar = nil;

after implementing this:

@property (retain) MyClass * myMemberVar;
@synthesize myMemberVar = _myMemberVar;

or this:

- (void) setMyMemberVar: (MyClass *) myMemberVar
{
    if (_myMemberVar != myMemberVar)
    {
        [_myMemberVar release];
        _myMemberVar = [myMemberVar retain];
    }
}

Categories – Since someone could override a method in your category with their own method making your method impossible to call, name your methods in a way to reduce that possibility.  The converse is also true.  For example, if you define a method in a category for an Apple-provided class, Apple could later come along and define that method in a class category and then all their calls will go to your method instead of theirs.

Key-Value Observers – The only thing not covered in that article that he covered in his talk was something that I started applying immediately:  When implementing key-value observers, make sure your observer only handles the notification if it knows that it is for your class.  This is a problem because your observer could be overriding the superclass’s observer and your observer must call the superclass’s observer if the notification isn’t for you.

To solve this, always pass specific to your class as the context parameter to the addObserver: method.

static void * s_kClassContext = &s_kClassContext;
...
[obj addObserver: self
      forKeyPath: "foo"
         options: NSKeyValueObservingOptionNew
         context: s_kClassContext];
...
- (void) observeValueForKeyPath: (NSString *) keyPath
                       ofObject: (id) object
                         change: (NSDictionary *) change
                        context: (void *) context
{
    if (context == s_kClassContext)
    {
        if ([keyPath isEqual: @"location"])
        {
            ...
        }
    }
    else
    {
        // Notification is not for us.
        [super observeValueForKeyPath: keyPath
                             ofObject: object
                               change: change
                              context: context];
    }
}