UITableView or UICollectionView Lazy Registration – dispatch_once

(UPDATE:  Don’t do this.  See discussion at the end)

Starting with iOS 6, UIKit added the following family of methods to UITableView and UICollectionView:

// UICollectionView
- (void)registerClass:(Class)aClass forCellWithReuseIdentifier:(NSString*)someIdentifier;

// UITableView  
- (void)registerClass:(Class)aClass forCellReuseIdentifier:(NSString*)someIdentifier;

Which makes it convenient to get a cell when you need one, without too much extra code. Doing it this way also ensures that you are designing your custom cells in their own subclass, rather than adding subviews to a view in a controller class. (I really like how Apple tries to make you become a better programmer by forcing you to write cleaner code and separate your concerns. See Why I DO use Interface Builder for more on that).

What I find sometimes annoying is forgetting to register this class somewhere (likely viewDidLoad), and it crashes at runtime. I also hate having to jump around code too much if it makes it less readable, so lately I’ve been using the following approach, which takes advantage of the pattern used when creating singletons; use the dispatch_once approach:

// in tableView:cellForRowAtIndexPath:

    static NSString *CellIdentifier = @"MyCell";
    static dispatch_once_t myCellOnceToken;  // define a variable name here that is specific to the context
    dispatch_once(&myCellOnceToken, ^{
        [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier];
    });

Maybe this approach will work well for you as well. Currently I’m not aware of the potential dangers of this, if there are any. Have to admit my knowledge of gcd up until this point has had a lot to do with recipes found on stack overflow.

UPDATE – There are dangers associated with this, so DON’T DO THIS. If you execute a dispatch_once block, but your collectionView is dealloc’d for whatever reason, the next time the newly created _different_ collectionView needs a cell, it won’t be registered.

SO, Moral of the Story:  Don’t forget to register your classes/nibs.  And do that in viewDidLoad, or somewhere right after you UICollectionView or UITableView is created.