9 posts in Fundamentals

Good Documentation

Every day I find myself relying on well documented code to work efficiently and productively. Good documentation helps me understand what a class or method does, what it was created for, or what that other developer was thinking when they wrote the module my code hinges on. Unfortunately, I have a history of preferring to read good documentation much more than I’ve preferred writing it, often because it seems too difficult and time consuming.

Lately however, I’ve been working on writing better documentation, and I’ve found it’s much easier than I expected. In this article, I’ll share some tips to help you document your own code more quickly and easily. We’ll look at what makes or breaks documentation, in which cases it is most vital, and what my process is for writing better docs.

Continue reading “Good Documentation” »

Better Class Variables with Settings Objects

What a week! WWDC 2014 was chock full of exciting news for developers, and we at Two Toasters ate it up. We’re super excited about extensions, custom keyboards, Hand-off, size classes, and of course Swift. There’s a lot to digest, but rest assured that we’ll be discussing iOS 8’s new APIs and technologies here in the coming weeks and months.

Today though, we’re going to discuss a really simple design pattern that works around one of Objective-C’s shortcomings: the lack of class variables. When we started working on URLMock, we found ourselves in a bind. Because of NSURLProtocol’s architecture, URLMock’s primary interface is the UMKMockURLProtocol class itself, not instances of it. To add an expected mock request, you have to use +expectMockRequest:; to verify that your URL code is working as expected, you have to use +verifyWithError:. This means that all our bookkeeping data—whether URLMock is enabled, whether verification is enabled, what mock requests are expected, which unexpected requests have been received, etc.—have to be stored at the class level.

Continue reading “Better Class Variables with Settings Objects” »

Translating Autoresizing Masks Into Constraints

Auto Layout has been a great improvement to the layout system on iOS. It allows expressing layout rules more explicitly and reduces the need for custom layout logic. I especially appreciate that you can mix Auto Layout with manual layout in cases where setting a view’s frame expresses the intended behavior more clearly.

Continue reading “Translating Autoresizing Masks Into Constraints” »

NSProxy, NSObject’s Lesser-Known Sibling

When we were testing URLMock, one of the first things we needed to verify was that we were sending the appropriate messages to NSURLConnection delegates. URLMock can send response data in multiple chunks, so we needed to check that certain delegate messages were received multiple times, while others were received once or not at all.

Continue reading “NSProxy, NSObject’s Lesser-Known Sibling” »

NSNumberFormatter and Objective-C Types

On a recent project, I ran into some very unexpected behavior with NSNumberFormatter. I was working with an API that delivered price information in cents. The price needed to be displayed in dollars. I decided to store the value in cents to maintain consistency with the API and to use NSNumberFormatter to generate the string for the UI. It seemed like a great solution.

Continue reading “NSNumberFormatter and Objective-C Types” »

UIAppearance for fun and profit

Building custom user interfaces is something our iOS development team encounters on a daily basis. Anything you can do to make it faster to develop or make your reusable controls easily customizable is an easy victory. UIAppearance gives you this easy victory.

While UIAppearance isn’t a brand new topic, it seems to get less love than it should. UIAppearance is a protocol available since iOS 5 that allows a developer to quickly configure the appearance of user interface controls provided by Apple. The fact that that your custom controls can take part in UIAppearance is talked about even less. This post will cover the basics of using UIAppearance and will explore adding support to your custom interface components.

UIAppearance Basics

You’ll be glad to know that UIAppearance is a straightforward API with almost no learning curve. To use it you need only know three things.

  • Properties and methods exposed to UIAppearance are decorated with the UI_APPEARANCE_SELECTOR attribute.
  • The class method +[UIControl appearance] will set the UIAppearance system to apply the specified properties when the control is created.
  • The class method +[UIControl appearanceWhenContainedIn:] will set the UIAppearance system to apply the specified properties when the control is created, but only when it is created in the specified containers.

That is all there is to it. UI_APPEARANCE_SELECTOR, + appearance, + appearanceWhenContainedIn:

Adding some style to UINavigationBar

Let’s see how this works. Say you want to style your UINavigationBar to be something a little different than the standard iOS style. First, look at the header file for UINavigationBar (you can find this by right-clicking on the symbol and choosing ‘Jump to Definition’ on it in Xcode).

Search for UI_APPEARANCE_SELECTOR. You’ll see it attached to many of the properties and methods, but not all. This is your guide to what is available by UIAppearance. In our case, the first time we see the attribute is with:

@property(nonatomic,retain) UIColor *tintColor UI_APPEARANCE_SELECTOR;

This means that the tintColor property is available for UIAppearance. This means I can now apply a global style affecting the tint to all UINavigationBar objects by telling the appearance proxy:

[[UINavigationBar appearance] setTintColor:[UIColor redColor]];

Now, no matter where a UINavigationBar is displayed within my app, it will be tinted red. Classy.

You can make this even more specific by telling the style to only apply when it is inside your own YOURCustomViewController. Consider the code:

[[UINavigationBar appearanceWhenContainedIn:[YOURCustomViewController class], nil]
                               setTintColor:[UIColor redColor]];

You’ve now told it to only apply the red tint color when a UINavigationBar is displayed inside a YOURCustomViewController. However, if I add a UINavigationBar to another view controller, it will not be tinted red. Only in the case that an instance of a UINavigationBar is in the hierarchy below an instance of a YOURCustomViewController will it be tinted red. Still classy.

All of these appearance styles can be applied as early as you like in your application. For example, you can set all your styles in -[UIApplicationDelegate application:didFinishLaunchingWithOptions:].

Supporting different iOS versions

As can often occur when working with any API, certain versions of can provide different functionality. How can we build an application level style when the available methods and properties on Apple’s controls are changing?

Thankfully, Objective-C is a dynamic language that allows runtime introspection on your objects. In a similar style to how you would ask your object if it -respondsToSelector:, you can ask a class if it’s instances respond to a method as well.

Consider this sample:

if ([UINavigationBar instancesRespondToSelector:@selector(setShadowImage:)]) {
    [[UINavigationBar appearance] setShadowImage:awesomeShadow];
}

The shadowImage property is new to iOS 6. Using +[NSObject instancesRespondToSelector:, we can inspect whether any instance of an object of this type will respond to this selector. Since you’ll be using the class type to apply an appearance, not an instance, this class method will tell you if this property can be used.

Using UIAppearance in your custom UI views

As stated earlier, you too can take advantage of UIAppearance in your custom views. Following the same pattern as seen above, let’s create a UIButton subclass that provides a property through UIAppearance.

I want to expose the font of the label on a UIButton. After subclassing, I’ll create a property that is decorated with “UI_APPEARANCE_SELECTORcalledtitleFont`.

@interface TWTButton : UIButton

@property (nonatomic, strong) UIFont *titleFont UI_APPEARANCE_SELECTOR;

@end

Next, I create the setter implementation and set the title label’s font property.

#import "TWTButton.h"

@implementation TWTButton

- (void)setTitleFont:(UIFont *)titleFont
{
    if (_titleFont != titleFont) {
        _titleFont = titleFont;
        [self.titleLabel setFont:_titleFont];
    }
}

@end

Now, you can set its appearance as if it was always available via UIAppearance:

[[TWTButton appearance] setTitleFont:myFont];

For a more detailed example of this, check out TWTButton.

Be careful using NSNotificationCenter with Blocks

NSNotificationCenter is a long existing mechanism for broadcasting messages to zero or many listeners. Many of Apple’s frameworks work deeply by notifiying you via an NSNotification when a message is posted. Traditionally, the workflow has been to follow a pattern similar to this:

- (void)viewDidLoad 
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(someMethod:) 
                                                 name:kMyNotificationIdentifier 
                                               object:nil];
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)someMethod:(NSNotification *)note
{
    // Message received
}

Blocks!

As of iOS 4 and the introduction of blocks, Mac and iOS developers can now use blocks to subscribe to NSNotification broadcasts. This new method also allows you to specify an NSOperationQueue to perform the block action on.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserverForName:kMyNotificationIdentifier 
                                                      object:nil 
                                                       queue:nil
                                                  usingBlock:^(NSNotification *note) {
        // message received
    }];
}

Wait, what?

Not so fast! Who is the observer? What removes this observer? What if you load several view controllers that do this? This block based method is not as simple as it appears. Reading the docs, we learn that addObserverForName:object:queue:usingBlock: actually returns an opaque observer that you are meant to retain, and subsequently -removeObserver with. Let’s take a look at what this looks like.

@implementation MyViewController
{
    id _notificationObserver;
}

// ...

- (void)viewDidLoad
{
    [super viewDidLoad];
    _notificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMyNotificationIdentifier 
                                                                              object:nil 
                                                                               queue:nil
                                                                          usingBlock:^(NSNotification *note) {
        // message received
    }];
}

// dealloc, or potentially a method popping this view from the stack
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:_notificationObserver];
}

As you can see, you still need to track the observer of a notification and remove it. Similar to what you would do if you were using the selector-based notification listener. Oddly enough, this is an example of a block-based API not really improving things. For this API, the selector-based NSNotificationCenter listener is a much simpler option as you don’t have to maintain the observer seperately.