How I do my singletons

This is something that comes up again and again.  How do you make a true singleton in Objective-C? I was just asked this the other night, so I decided to write up my version of an Objective-C singleton.

For starters, there’s an example in the documentation on how you could make a singleton. It’s a pretty bizarre implementation. StackOverflow.com has a nice long discussion on what people consider acceptable singletons. Peter Hosey wrote an in-depth post about it a while back as well, with a different example of what he considers a good singleton.

Go read those articles, then come back.

Have you read them yet? Good.

I think Peter’s overview of what makes a singleton is very good. In particular, he has several criteria that, if met, help define a singleton. They are:

  1. +sharedFramistan always returns the same object.
  2. +alloc/-init always produce the same object (which, itself, is the same object as +sharedFramistan).
  3. +alloc/-init will not return an object confused by multiple init messages.
  4. Over-releasing causes a crash.
  5. Keeping +alloc/+allocWithZone:/-retain balanced with release never causes a crash.
  6. If [super init] returns a different object, +alloc/-init won’t break.

Over the couple years, I’ve developed my own singleton pattern. I think it’s pretty simple, it gets the job done, and it’s fairly idiot-proof. It does have a drawback, which is that the singleton exists for the lifetime of the process; it is not lazily created. If that’s a problem for you, well then this singleton probably isn’t for you. Other than that, it has served me very well.

So, without further ado, here it is:

// DDFramistan.h
@interface DDFramistan : NSObject

+ (id) sharedFramistan;

@end

// DDFramistan.m

static DDFramistan *_sharedFramistan = nil;

__attribute__((constructor)) static void construct_singleton() {
  NSAutoreleasePool * p = [[NSAutoreleasePool alloc] init];
  _sharedFramistan = NSAllocateObject([DDFramistan class], 0, nil);
  [p drain];
}

__attribute__((destructor)) static void destroy_singleton() {
  NSAutoreleasePool * p = [[NSAutoreleasePool alloc] init];
  NSDeallocateObject(_sharedFramistan), _sharedFramistan = nil;
  [p drain];
}

@implementation DDFramistan

+ (id)sharedFramistan {
  return _sharedFramistan;
}

+ (id) allocWithZone:(NSZone *)zone {
  return [[DDFramistan sharedFramistan] retain];
}

@end

The only really weird things going on here are those two functions, construct_singleton() and destroy_singleton(). What’s up with those? Basically, by tacking that __attribute__((constructor)) onto the function declaration, this function will get invoked before execution enters main(). As such, we have to set up an NSAutoreleasePool for the off-chance that we happen to create any autoreleased objects during singleton creation. Also, I’m using the NSAllocateObject() function, which is pretty much the same thing as class_createInstance(). That’s going to allocate a new object for me on the heap, with all of the members of that object set to 0 (ie, it’s essentially using calloc()).

Similarly, the __attribute__((destructor)) function is one that will get executed after returning from main() (or exit()). This one isn’t quite as necessary, since if the program is exiting, all the memory is going to get cleaned up anyway. However, if you’ve got shared resources (file descriptors, etc), this would be the place to clean them up. Again, we wrap the deallocation in an NSAutoreleasePool to catch any autoreleased objects that may get created in the process (which would be weird, but not impossible).

As for the methods on the singleton itself, they’re really straight forward:

  • +sharedFramistan returns our singleton
  • +allocWithZone: returns the static singleton, retained (just like it’s supposed to)
  • Since we have no -init method, we’ll simply inherit the one belonging to NSObject. -[NSObject init] is documented to simply return self, so we’re safe to invoke it as many times as we want.

Other than that, it’s a perfectly normal Objective-C object. Let’s go over Peter’s list and see how we did:

  1. +sharedFramistan always returns the same object.
    Yep, we got that.

  2. +alloc/-init always produce the same object (which, itself, is the same object as +sharedFramistan).
    Yep, we got that too.

  3. +alloc/-init will not return an object confused by multiple init messages.
    Since the init method does do anything, this is easily accomplished.

  4. Over-releasing causes a crash.
    We’re not doing anything bizarre with memory management, so if you over-release the singleton, it will get deallocated prematurely, and accessing it after that will cause your program to crash. So… check.

  5. Keeping +alloc/+allocWithZone:/-retain balanced with release never causes a crash.
    Again, we’re good here. As long as you don’t over-release, this object will never go away.

  6. If [super init] returns a different object, +alloc/-init won’t break.
    Since we don’t implement -init, we don’t have to worry about this.

Looks pretty good!

Now, the moment we’ve all been waiting for…

Is DDFramistan a true singleton?

NO.

DDFramistan is not a true singleton. A true singleton would never allow another instance of the object to be created under any circumstances. Unfortunately, Objective-C has fun things like NSAllocateObject() and class_createInstance() that allow us to easily bypass all of the normal object creation business, and there’s nothing we can do about that (that I can think of). So while it’s unlikely that you would ever create another instance of DDFramistan, it’s not impossible. And therefore, this is not a true singleton.

But it’s probably good enough (and it’s about as close as you can get).


History

  • 24 Feb 2011 - Original post
  • 24 Feb 2011 - removed unnecessary init method, as suggested in the comments

asker

heapify-deactivated20130709 asked: Why do Strings in Objective-C have to be preceded with an @?

Simple: because if you left it off, it wouldn’t be an NSString*. It’d be a char *. Any time you see the @ symbol in Objective-C code, you can know that it’s so that the compiler can do something special there that C doesn’t natively support.

So with that in mind, we have:

  • @catch: declare a scope for catching a thrown execution
  • @class: forward declare a class
  • @compatibility_alias: specify an alias for a class name
  • @dynamic: specify that property accessors will by dynamically implemented at runtime
  • @encode: ask for a character array representing the type of a variable
  • @end: close an interface declaration or an implementation block
  • @finally: declare code that will be executed after an @try and/or @catch block execute
  • @implementation: implement a class definition
  • @interface: define a class API (also used for categories and class extensions)
  • @optional: declare the optional nature of protocol methods
  • @package: declare the scope of ivars
  • @private: declare the scope of ivars
  • @property: declare a class property
  • @protected: declare the scope of ivars
  • @protocol: declare a list of methods that conforming objects might implement
  • @public: declare the scope of ivars
  • @required: declare the required nature of protocol methods
  • @selector: declare the the stuff that immediately follows in the parentheses is a method name
  • @synchronized: declare a section of code that is atomic
  • @synthesize: direct the compiler to generate accessor methods for properties (that you haven’t implemented yourself)
  • @throw: throw an NSException
  • @try: begin a block in which an exception might be thrown
  • @"": declare a constant string

That’s all I can remember off the top of my head. I’m sure I’ve forgotten one or two. A more complete list (with better explanations) can be found in the documentation.

asker

mahmoudhossam-deactivated201107 asked: Since this is an Obj-c blog,I have a question for you

why would they make another C with OOP,what's wrong with C++?

It sounds from your question like Objective-C has only been around for a couple years. Believe it or not, Objective-C is an old language! It was invented in 1986 by Tom Love and Brad Cox (only 3 years after C++). It was adopted by NeXT as the lingua franca of the NeXT OS, and was the language that Sir Tim Berners-Lee used to write the world’s first web browser.

Objective-C and C++ were created with very different purposes. The former was an experiment in combining the dynamism of Smalltalk on top of the C language. C++, on the other hand, was built to add the object oriented features of Simula to C, but without suffering from Simula’s performance problems.

PC Week summed up this difference nicely in their 3 Nov 1997 edition:

Objective-C is the result of adding object facilities to C with the goal of making programmers more productive. The result differs greatly from C++, which adds objects to C without making computers less efficient: quite a different goal.

I’ve found this to be the case in my own use of the language. I’ve learned several languages over the past decade, and Objective-C is the only language I’ve actually enjoyed using. Of course, each language has its flaws (including Objective-C), but Objective-C gives me the organization of an object-oriented language like C++ or Java, the power of a dynamic and flexible runtime like a scripting language, all built on top of the power of C. There are tradeoffs to this (Objective-C tends to be slightly slower than C++), but for me, the benefits far outweigh the costs.

asker

cbarrett asked: I've really been enjoying your posts, but you don't have any personal information on your site, as far as I could find. Who are you?

No one of consequence…

My name is Dave DeLong. I’m a frameworks engineer at Apple, where I work on the UIKit framework. I spend my spare time with my family and playing with the Objective-C runtime. I also believe that the existence of chocolate and peanut butter are proof that there is a God, and that He loves us.

Using custom functions with NSExpression

There are a bunch of built-in functions in the NSExpression class that allow you to do some pretty neat stuff. They are: average:, sum:, count:, min:, max:, median:, mode:, stddev:, add:to:, from:subtract:, multiply:by:, divide:by:, modulus:by:, sqrt:, log:, ln:, raise:toPower:, exp:, ceiling:, abs:, trunc:, random, random:, now, floor:, uppercase:, lowercase:, bitwiseAnd:with:, bitwiseOr:with:, bitwiseXor:with:, leftshift:by:, rightshift:by:, onesComplement:, and noindex:. That’s a lot of functions! You have your arithmetic functions, some multi-parameter functions, some bitwise functions, and a few miscellaneous ones thrown in for good measure.

But… what if you want to find the factorial of a number? Or use any sort of trigonometric function? Or say you wanted to do something much more complex? Are you out of luck?

Fortunately, no. There is a way to do custom functions in NSExpression, with the downside that the syntax is a little bit more complex than your standard functions.

The built-in functions can be written as if they were actual functions: now(), sqrt(42), 6 * 9, etc. Unfortunately, we cannot do that with our custom functions. Oh well. Let’s get over that and move on.

The Syntax

The syntax for all functions is:

FUNCTION(operand, 'function', arguments, ...)

In a nutshell, the result of the function is the result of invoking the function method on operand, while passing in the arguments as parameters to the method.

If we dive into one of the NSExpressions produced by a standard function, we learn some interesting things. Let’s example the function “6*9”.

NSExpression * e = [(NSComparisonPredicate *)[NSPredicate predicateWithFormat:@"6*9 = 1"] leftExpression];

The -operand of this expression is another NSExpression. In the case of these built-in functions, it turns out that it’s a constant value expression encapsulating a Class object of type _NSPredicateUtilities. Some runtime introspection on this object shows that it has a whole bunch of class methods that correspond to all of the built-in functions, along with one that’s not listed in the documentation: castObject:toType:. We previously discussed using this function with advanced date predicates.

The operand is an NSExpression (as opposed to an id), because the object receiving the method could be the result of another expression.

The function in our multiplication expression is “multiply:by:”, as we would expect.

The arguments to our multiplication is an NSArray of NSExpression objects. They are expressions for the same reason that the operand is an NSExpression. In our example, we have two expressions, both representing NSNumbers as constant values.

Custom Functions

Now that we understand the syntax behind FUNCTION(), it should be fairly obvious how to go about making our own functions. Here’s what we need:

  • An object on which to operate.
  • A method to invoke
  • Parameters to pass in (optional)

So let’s say we want to add a factorial function. We have two options on how to approach this:

  1. Make our factorial method receive the number as a parameter
  2. Make our factorial method operate on a number directly

I personally prefer the latter approach, since the syntax is slightly less complicated. Here’s what we would do:

@interface NSNumber (FactorialExpression)

- (NSNumber *) factorial;

@end

@implementation NSNumber (FactorialExpression)

- (NSNumber *) factorial {
  double baseValue = [self doubleValue];
  double result = tgamma(baseValue+1);
  return [NSNumber numberWithDouble:result];
}

@end

(This method uses the Gamma Function, which allows for computing the factorial of non-integral numbers)

Then in our format string, we would express it like this:

FUNCTION(4.2, 'factorial')

If we evaluate that expression, we get 32.57809605033135, as we were hoping! The key thing here is realizing that 4.2 will be boxed in an NSNumber, which means that the factorial method will be invoked on NSNumber.

Venturing Toward the Absurd

OK, we’ve got basic functions down. What about functions that take arguments? For this next example, we’ll take a look at a custom function being used in StackKit, a framework for accessing the Stack Overflow API.

At the heart of StackKit is a URL generation system that will turn a combination of an NSPredicate, an NSSortDescriptor, and a Class into an HTTP GET request that can be used to retrieve data from one of the Stack Exchange sites (like http://stackoverflow.com). Due to the limited nature of the API, only certain predicates and sort descriptors are allowed, and only in very specific combinations.

One of the parts of “validating” an NSPredicate is to verify that it is only using allowed keyPaths, and that these keyPaths are being compared with specific operators. Each of the “RequestBuilder” classes vends an NSDictionary called the recognizedPredicateKeyPaths. This dictionary is a map of keyPaths (as the key) to an NSArray of NSNumber objects. The NSNumbers box an NSPredicateOperatorType.

Since each builder recognizes different keyPaths and different operators, I had to get a little creative. Here’s what the code looks like:

p = [NSPredicate predicateWithFormat:@"FUNCTION(%@, 'sk_matchesRecognizedKeyPathsAndOperators:', SELF.recognizedPredicateKeyPaths) == YES", predicateToValidate];
[builders filterUsingPredicate:p];

In this case, predicateToValidate is the user-supplied NSPredicate. I’m going to be passing this predicate in as the operand to my FUNCTION. The method that will be invoked on it is @selector(sk_matchesRecognizedKeyPathsAndOperators:), which is conveniently provided via an NSPredicate category. Finally, the argument to this function is the dictionary of the current request builder. If the sk_matchesRecognizedKeyPathsAndOperators: method returns YES, then we’ve passed this particular step of the validation.

The code for the NSPredicate method is fairly simple; it simply iterates through all of the keys in the NSDictionary, then extracts the subpredicates of the “predicateToValidate" for each key. Of these subpredicates, if there’s one that’s using an operator that’s not recognized, then we abort and return NO. Otherwise we’ll get to the end, find that all of our subpredicates are using allowed operators, and return YES.

The result of those two lines of code is that the builders array will be filtered to only contain the builders that allow the left keyPaths and operators that are specified in the user-provided predicate.

(For more fun, exciting, and absurd uses of NSPredicate, check out SKRequestBuilder.m.)

A Caution

One of the things to be wary of when using custom functions is that all of the parameters to the method must be objects, and the return value of the method must also be an object! This means that you cannot do:

[NSPredicate predicateWithFormat:@"FUNCTION('a', 'isEqual:', 'a') == YES"];

If you try to evaluate that predicate, it will crash. NSExpression is attempting to cast the result of the isEqual: method as an object. However, (id)1 is not an object recognizable by Objective-C, no matter how you cast it.

Instead, if you needed to do this, you’d add a method that simply boxed the result in the appropriate NSValue object and use that method:

@implementation NSString (CustomFunction)

- (NSNumber *) dd_isEqual:(id)other {
  return [NSNumber numberWithBool:[self isEqual:other]];
}

@end

...

FUNCTION('a', 'dd_isEqual:', 'a')

This will work just fine.

Wrap Up

Custom functions in NSExpression are pretty neat. You don’t find yourself using them very often, but when you need them, they can be extremely handy!