Archives For Objective-C

Dot notation is okay, after all.

There, I said it.

I’ve been a staunch opponent of dot notation. I saw it as obscuring messaging, and encouraging programmers to violate the Law of Demeter through chained dots. I went so far as to characterize dot notation as an Objective-C code smell.

So it may surprise you to learn that I’ve recently adopted dot notation in my code! Here’s how it happened…  Continue Reading…

There are subtle issues around #import order. You may not believe me — until you try reusing code in a new project.

Unfinished Bridge 1” by Jason Thomas, used under CC BY-NC-SA 2.0 / Altered by Jon Reid

In #imports gone wild! we looked at the problems caused by having too many #import directives. But it’s also possible that you have too few, resulting in bad header files — especially if you don’t pay attention to #import order in your .m files.

Minimal and complete

When it comes to imports, header files should satisfy these two conditions:

  • They should be minimal
  • They should be complete

“Minimal” just means a header file should import no more than it needs.
“Complete” means the header file imports everything that needed to compile it. Consider Continue Reading…

In my screencast of UIViewController TDD, I used an example of incrementing a counter and couldn’t help but give a slight aside: “We’ll increment it… ++count, instead of count++, please.”

WHAT YOU SAY!!

<rant>
I blame Apple for propagating poor incrementing style. Programming with Objective-C starts with the statement, “[Objective-C is] a superset of the C programming language.” But every example they give of incrementing a value uses someInteger++, ignoring the fact that C has two different increment operators!

  • Post-increment: count++
  • Pre-increment: ++count

The Wikipedia article Increment and decrement operators gives clear examples of the difference.

What performance impact will it make? None. The extra code for post-increment semantics is probably optimized away by today’s compilers. Even if it’s not, it’ll still have almost no impact. So what does it matter?

It matters to the reader. It matters because it shows a lack of familiarity with the language’s operators, which doesn’t fill me with confidence in your code. It matters because Objective-C Is Still C (Not Java!)

Say what you mean, rather than relying on side-effects.
</rant>

Question: Do language subtleties really matter? Leave a comment below.

I sometimes talk to myself. Our classes often do. But there are a couple of places where doing so is risky in Objective-C: init and dealloc.

"The Self-Talk Solution"

[This post is part of the Code Smells in Objective-C series.]

Here’s something I see a fair bit in code for Objective-C init and dealloc. I’ll give a simple example. Can you tell what’s wrong?

- (id)initWithFoo:(id)foo
{
    self = [super init];
    if (self)
        self.something = foo;
    return self;
}

- (void)dealloc
{
    self.something = nil;
    [super dealloc];
}

Hint: It’s those self-dots. They have a tendency to lull people into thinking they’re simple assignments. But remember, dot notation conceals messaging.

Let’s avoid dot notation and try again: Continue Reading…

Dot notation for messaging isn’t just an Objective-C code smell. It’s evil, I tell you!

Update: I recently changed my mind! See my post In Which I Embrace Dot Notation…

Dot notation: 100% PURE EVIL

[This post is part of the Code Smells in Objective-C series.]

…OK, so that’s hyperbole. I do manage to coexist with dot notation in projects that have it. But I won’t write it myself. Here are 3 reasons I avoid dot notation in my code: Continue Reading…

When used well, precompiled headers can save you precious compilation time. But when used poorly, precompiled headers can hide problems in your source code that you may not notice until you try to reuse parts of it for another project.

crutches

my crutches” by dmitiri_66, used under CC BY-NC 2.0

[This post is part of the Code Smells in Objective-C series.]

Precompiled headers were invented for one purpose: to make compiling faster. Rather than parsing the same header files over and over, these files get parsed once, ahead of time. Speed is important! The faster you compile, the faster you can complete the feedback loop to see if recent changes were successful.

In Xcode, you do this by including the header files you want in a “prefix header,” and enabling “Precompile Prefix Header” so they get precompiled. But the idea behind a prefix header is different from precompiling. A prefix header is implicitly included at the start of every source file. For example, if your prefix header is Prefix.pch, it’s like each source file sneaks

#import "Prefix.pch"

at the top of the file, before anything else. This can be handy for project-wide #defines. (Just remember that in general, #defines are a code smell.)

It’s also handy for precompiled headers. The fact that every source file includes these precompiled headers is an artifact of being in the prefix header.

And this is where things start to go wrong… Continue Reading…

We all use factory methods, a.k.a. convenience methods. We often write them ourselves. But there’s a wrong way, and a right way, to write a factory method for your Objective-C class. Do it wrong, and you cut off some features of Objective-C. Do it right, and you open yourself up to new object-oriented possibilities.

Big [self alloc] factory

Volkswagen Factory Wolfsburg/Germany” by Werner Kunz, used under CC BY-NC-SA 2.0 / Altered by Jon Reid

Let’s back up and review what we mean by a factory method. This is a convenience method that you invoke on a class to say, “Make me one of your kind.” (Some folks call this a “convenience constructor” which is odd to me, because the underlying mechanics are quite different from Java or C++.)

Factory method: The wrong way

Let’s say we have a simple class:

@interface Foo : NSObject
- (id)init;
@end

To create an autoreleased Foo object, we’d write

    Foo *aFoo = [[[Foo alloc] init] autorelease];

But if you do this a lot, it becomes tedious and can clutter your code. So let’s create a factory method.

At this point, it’s tempting to copy and paste into the body of the new method:

+ (Foo *)foo
{
    return [[[Foo alloc] init] autorelease];
}

Looks fine. Everything works. So what’s the problem? Continue Reading…

How do you switch your app between a staging URL (for development and testing) and a production URL (for real world use)? I’ve changed my mind about my approach, because one size doesn’t fit all.

In 9 Code Smells of Preprocessor Use, I originally suggested that instead of using the preprocessor, it would be better to use a plist. Here’s the preprocessor code smell:

#if STAGING
static NSString *const fooServiceURL = @"https://dev.foo.com/services/fooservice";
#else
static NSString *const fooServiceURL = @"https://foo.com/services/fooservice";
#endif

I wrote, “Instead of defining these URLs in your code, treat them as resource definitions and place them in a plist, organized by type.” Continue Reading…

Like all C-based languages, Objective-C files usually come in pairs: there’s a header file, and an implementation file. Either can use the #import directive to include other header files. And if you’re not careful, it’s easy to create an explosion of file dependencies. What are the consequences? How do we tame #import dependencies?

#imports (not Girls) Gone Wild

Girls Gone Wild Tech” by Thomas Hawk, used under CC BY-NC 2.0 / Altered by Jon Reid

[This post is part of the Code Smells in Objective-C series.]

File dependencies

Unnecessary #imports in a .m file are a nuisance. Why? Because it forces you to have those other files in your project. This isn’t a big deal when you’re working on a single project, but immediately causes trouble when you start a new project and want to reuse some source files.

But unnecessary #imports in a .h file are even worse: the problem grows exponentially! That’s because a header imports another header, which imports another header, and so on. Think of it as a dependency graph:

Dependency graph

Say A.h imports B.h and C.h. But B.h also imports D.h. So to add A to your project, you have to pull in B, C and D as well. And this graph is about as simple as it comes. If unnecessary #imports aren’t kept pruned away, the dependency graph will get out of hand. Continue Reading…

Do you have your C book?

Do you have your K&R book?

October 2011 saw the passing of giants:

Simplicity. Power.

  • Steve Jobs. You work with his toys everyday.
  • Dennis Ritchie, inventor of the C programming language, co-inventor of Unix. You work with his stuff everyday (but we forget that).
  • John McCarthy, inventor of Lisp. We use the descendants of his invention every day (without realizing it).

By his vested Interweb powers, Tim O’Reilly has declared that October 30 be Dennis Ritchie Day. In his honor, I wanted to write something that’s been bothering me about the way people are learning Objective-C:

Objective-C is still C !

As a programmer, your most fundamental tools are the programming languages you use. If you don’t know the tool, you simply won’t be able to express things with both simplicity and power. And while I’m glad for the sudden interest in Objective-C, I’m troubled that so many people treat it like some kind of bastardized Java. They jump straight into messaging syntax and Foundation classes, while bypassing the powerhouse that’s available to them.

That powerhouse is the C language. Continue Reading…