More on the Optionals!

We can chose to write stable code or we can hand-wave stuff that “shouldn’t fail”. I’m extremely wary of the pattern that I keep seeing from Apple about ! and Optional… I find it odd that Apple is promoting the use of the ! pattern.

An initializer defined with init can be made failable by adding a ? or a ! after the init, which indicates the form of optional that will be produced by constructing an object with that initializer. For example, one could add a failable initializer to Int that attempts to perform a conversion from a String:

extension Int {
    init?(fromString: String) { 
        if let i = fromString.toInt() {
            // Initialize 
            self = i
        } else {
            // return nil, discarding self is implied
            return nil
        }
    }
}

Source: Apple Developer Blog: https://developer.apple.com/swift/blog/

If we change the init? above to init! (which the description above tells us is perfectly valid)…

let value = Int(fromString: "abc")
return value + 1

BOOM! Hello my EXC_BAD_INSTRUCTION friend.

Look, sometimes your code really should only return nil in the most dire of circumstances, ok… but is the right behavior to crash your app? Even if it is, it should not be so easy to enable the return of nil from something that should practically never return nil, such as memory allocations handled by the system.

One of Swift’s goals is this: “Understanding and properly handling cases where objects are nil is fundamental to the frameworks, and Swift code makes this extremely easy.” (Source: https://developer.apple.com/swift/)

I truly believe this behavior is leading us away from that – I’d go so far to claim it’s the antithesis of it, but that may be too extreme for some.

As developers, we want to be able to write both safe and stable apps. The ! is leading us down the path of safe but crashy apps. We’re going to get there just as we got there with * and dereferencing null pointers. Of course, everyone knows not to do it… yet sometimes we forget. And to those new to the language, they might not know better.

See: Pointer fun with Binky.

I would much rather see APIs defined like this:

@unsafe_force_unwrap func init(fromString: String) { ... }

Give support for the feature when needed, but people will be much less prone to accidentally doing it. It needs to be marked as unsafe; currently there is no really indication other than experience with the language.

This also gives us the ability to have compiler warnings/errors when these are used so we can much easier audit those code usages.

More on the Optionals!

Optionals Beware

Update: 10/20/2014 I was inappropriately applying ? to the key lookup, which of course, does nothing. It is simply not needed.

Optionals… that pesky little safe, but sometimes dangerous, construct in Swift. It's not new or unique, but they do work a bit different than other languages.

GIVE ME THE VALUE!!! In John Siracusa's Yosemite review, there's a section on Swift. In it, while talking about safety and optionals, there's a trap in here.

let ages = [
    "Tim":  53,  "Angela": 54,  "Craig":   44,
    "Jony": 47,  "Chris":  37,  "Michael": 34,
]

let people = sorted(ages.keys, <).filter { ages[$0]! < 50 }

swift

Do you spot it? It's the use of !.

And that's the problem with the !, in some cases, it is safe to use it… until you start to modify the code around the area, then it might start to get dicey.

There is a safe way to write the code that will never cause your program to crash, regardless of the refactoring you do:

let people = sorted(ages.keys, <).filter { ages[$0] < 50 }

Removing the ! provides all the safety we need. The comparison operators already handle optionals. In the case of <, when the left hand side is nil, the result is always true.

Whenever you see the ! in your code, BE CAREFUL!!! I'd go so far as recommending to never use it. There are safer ways, though, they are sometimes it is a bit more verbose.

So instead of writing this:

func |||<T>(opt: T?, defaultValue: T) -> T
{
    return opt != nil ? opt! : defaultValue
}

swift

Write this:

func |||<T>(opt: T?, defaultValue: T) -> T
{
    if let opt = opt { return opt } else { defaultValue }
}

Update: Yes, you could use ??, that's not the point. The point is just showing how to write the forced unwrapped version in way that doesn't require forced unwrapping.

Beware of the optional!

Optionals Beware

Stop to Smell the Roses

I would love to build a better Objective C language. It would be a language that embraces the functional programming world and the imperative programming world, the world of dynamic runtimes and static types, and build a bridge to the future from the past.

The following is taken from some of my notes, so the code samples might be a bit rough.

Class definitions would be simple and straight forward:

' All classes derive from `NSObject` by default. Use the `derives <class>` syntax
' to subclass differently. Also, use `implements <type>, <type>, ...` for protocols.
interface Person
    ' The `let` keyword creates readonly properties.
    let firstName :: NSString
    let lastName :: NSString

    ' The `var` keyword creates read/write properties.
    ' The `[copy]` is the attribute applied to the property, in this case
    ' all writes to `emailAddress` will create a copy of the incoming value.
    var emailAddress :: NSString [copy]

    ' initializer with parameters, defaults to returning `instancetype` in ObjC
    def initWithFirstName::NSString lastName::NSString
        _firstName = firstName
        _lastName = lastName

    ' a message name with a single parameter, defaults to returning `void` in ObjC
    def say message::NSString
        log("\(firstName) says \"\(message)\"")

    ' A simple message that returns a `NSString`
    def fullName -> NSString
        return "\(firstName) \(lastName)"

All function definitions would allow for partial application:

def sum x: Number -> y: Number -> Number
    return x + y

let sum1 := sum 1
let sum2 := sum1 2
let full := sum 3 4
log "sum of 1 + 2 = \(sum2)"

Syntax would be light and free of unnecessary tokens:

' No difference between message calls and function calls
let david := Person newWithFirstName:"David" lastName:"Owens
david.emailAddress := "david@owensd.io"

' Use () to group nested calls for ordering
let sally := (Person alloc) initWithFirstName:"Sally" lastName:"Sue"
sally say:"Hello all the peoples!"

let ages = {
    "Tim":  53,  "Angela": 54,  "Craig":   44,
    "Jony": 47,  "Chris":  37,  "Michael": 34,
}

let people = filter (key => ages[key] < 50) (sort < (ages allKeys))

All of this code can be re-written to ObjC (by a tool). I have prototypes of some of it and manual constructions of others. I know it’s possible and it allows for full interop between this language dubbed Proteus and ObjC.

But… what’s the point?

I don’t mean to ask that as a submission or a throw-in-the-towel remark. But really, what’s the point? Where do I want to go with it? It would be fun to go through designing this out and getting all of the main scenarios working – I haven’t done that since my college days. I don’t even think it’s a super amount of work. But the edge cases will suck. The considerations of certain C constructs will get a bit dodgy. And in order to really get the performance up to par, I’m likely going to need to emit LLVM code instead of going through the ObjC source code, or worse (in my opinion), need to make changes to LLVM or Clang like the Eero project did. And this is before I even get into editor support, code highlighting, debugging, etc…

Swift has it’s warts. It’s a baby that’s trying to grow up quickly in a world that is harsh. The question I’ve been asking myself, both through these posts and throughout the weeks is really this: are Swift’s warts and ugly places worse than those of Objective C’s? Will they be tomorrow?

There will be a lot I miss about ObjC. Hopefully we’ll see more of that over time. But I think it’s time for this station to get back to it’s regularly scheduled program.

Stop to Smell the Roses

Building a Better Objective C

If you’ve been following along with my recent posts regarding enums and Objective C, you’ll notice a theme: Objective C is quite capable of expressing what we want, it’s just extremely verbose, especially compared to the improved syntax that Swift brings to the table.

There are many significant drawbacks to Swift, especially when you need to interop with ObjC code. In this world, we need something better. We need to be able to transparently bridge between the world of modern syntax and conveniences without being shackled to the days of C programming, while at the same time, being able to maintain 100% interop with all of our existing ObjC code.

We could continue to suffer through the ObjC syntax, or, we can do something about it.

Framing the Solution One solution to solving the problems I exposed in the series with enums is to use a bunch of MACROs. That works, but it doesn’t get us nearly where we want to be: a modern, sleek syntax that is both easy to write, and more importantly, easy to read and reason about.

This is where we want to be:

enum CompassPoint: North | South | East | West

That’s it. That’s all it should take to define one of the “traditional” enums.

enum Barcode:
  | UPCA(numberSystem :: int, manufacturer :: int, product :: int, checkInt :: int)
  | QRCode(code :: NSString)

And above is what the “associative value” enum looks like. I’d like to call out something here, we actually have more information encoded in the enum then Swift here – we capture the name of the components1. This adds much more clarity to what the values actually are.

And finally, the raw values:

enum ASCIIControlCharacter :: NSString:
  | Tab := "\t"
  | LineFeed := "\n"
  | CarriageReturn := "\r"

You might be wondering at how we are going to accomplish this. Well, it’s actually pretty straight forward. Here are the items we’ll be building:

  1. A parser for our enum syntax
  2. A tool to convert our parse tree to ObjC code

That’s it. We don’t actually need anything else2. I’ll show how we can leverage Xcode’s built-in extensibility points to give us nice error reporting and seamless integration of our new enum definition.

I will be calling this new language: Proteus.

Building the Parser There are basically two ways to generate the parser: handwrite one or use some tools to generate one from a grammar. I’m going to handwrite our parser, primarily because our enum grammar is quite simple and it’s really easy to provide very friendly error messages with a handwritten parser.

Note: I’ll only be showing building the most simple of parsers accepting only the basic version of the enum. The full github link will be posted at the end. Overtime I’ll continue to add support more features.

The work is going to be broken up into the following components:

  1. Scanner – this is going to break up the input file into a set of tokens.
  2. Analyzer – this is going to take the tokens from the Scanner and apply meaning to them, returning an array of Constructs.
  3. Construct – a representation of the different type of language constructs, such as enum or func.
  4. Rewriter – a function that can take a Construct and turn it into the appropriate Objective C header and implementation files.

I will be writing the components in Swift – I like the irony of building a better Objective C in a language that I think didn’t live up to that promise. =)

The full source for the project can be found here: https://github.com/owensd/proteus3.

If you take a look at the code for the scanner (in lexer.swift), the output for the CompassPoint declaration are the following tokens:

  1. Token(Keyword) “enum”
  2. Token(Identifier) “CompassPoint”
  3. Token(Colon) “:”
  4. Token(Identifier) “North”
  5. Token(Pipe) “|”
  6. Token(Identifier) “South”
  7. Token(Pipe) “|”
  8. Token(Identifier) “East”
  9. Token(Pipe) “|”
  10. Token(Identifier) “West”

This input is passed into the Analyzer which outputs an Enum construct.

Enum:
  typeName = "enum"
  identifier = "CompassPoint"
  options = [
    "North",
    "South",
    "East",
    "West"
  ]

Then there is the rewriteEnumToObjC rewriter function. The full code for that is below:

private func rewriteEnumToObjC(value: Enum) -> (header: String, implementation: String)
{
    var header = "@interface \(value.identifier) : NSObject\n\n"

    var implementation = "#include \"\(value.identifier).h\"\n\n"
    implementation += "#define RETURN_ENUM_INSTANCE() \\\n"
    implementation += "    static \(value.identifier) *instance = nil;\\\n"
    implementation += "    static dispatch_once_t onceToken;\\\n"
    implementation += "    dispatch_once(&onceToken, ^{\\\n"
    implementation += "        instance = [[\(value.identifier) alloc] init];\\\n"
    implementation += "    });\\\n"
    implementation += "    return instance;\n\n"

    implementation += "@implementation \(value.identifier)\n\n"

    for option in value.options {
        header += "+ (\(value.identifier) *)\(option.name);\n"
        implementation += "+ (\(value.identifier) *)\(option.name) { RETURN_ENUM_INSTANCE(); }\n"
    }

    header += "\n+ (NSArray *)values;\n"
    implementation += "\n+ (NSArray *)values\n"
    implementation += "{\n"
    implementation += "    static NSArray *values = nil;\n"
    implementation += "    static dispatch_once_t onceToken;\n"
    implementation += "    dispatch_once(&onceToken, ^{\n"
    implementation += "        values = @[ "

    for (idx, option) in enumerate(value.options) {
        implementation += "\(value.identifier).\(option.name)"
        if (idx != value.options.count - 1) {
            implementation += ", "
        }
    }

    implementation += " ];\n"
    implementation += "    });\n\n"
    implementation += "    return values;\n"
    implementation += "}\n"

    header += "\n@end\n"
    implementation += "\n@end\n"

    return (header, implementation)
}

swift

The basic concept is to literally just write the header and implementation files as you would normally.

With each of those components in place, it’s time to hook it up!

Integration with Xcode If you download the project I linked, there will be a command-line tool called protc. It takes two parameters:

  1. -file – the path to the .prot file that contains our enum definition
  2. -output – the path that the .h and .m files will be written to

So here’s the magic… Xcode has these things called “Build Rules”. It’s basically how anything gets compiled within Xcode. Well, we can create our own build rules for our .prot files.

Step 1: Build Rules To do that:

  1. Select your project in the project navigator
  2. Select the target for your app/tool
  3. Select the “Build Rules” tab in the project editor
  4. Add a new build rule

The script will be filled in with this content:

rm "${DERIVED_FILE_DIR}/${INPUT_FILE_BASE}.h" 2> /dev/null
rm "${DERIVED_FILE_DIR}/${INPUT_FILE_BASE}.m" 2> /dev/null
/Users/owensd/Library/Developer/Xcode/DerivedData/protc-ecehehjngfljckcirxwdltnqqayl/Build/Products/Debug/protc -file ${INPUT_FILE_PATH} -output ${DERIVED_FILE_DIR}

Then be sure to set the “Output Files” to:

  1. $(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).h
  2. $(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).m

Here’s a screenshot of what it looks like:

Custom build rules allow us great flexibility.

: .caption

Step 2: Create your .prot file Next, create your .prot file just as you would any file. The trick is to add it to your “Compile Sources”.

  1. Select your project in the project navigator
  2. Select the target for your app/tool
  3. Select the “Build Phases” tab in the project editor
  4. Add your .prot file to the list of “Compile Sources”

Don’t forget this step or nothing will seem to be working!

: .caption

Step 3: Use your new enum! That’s really it. Now when you build your project, the .prot will be processed and in turn the generated .m file will be compiled into your project’s target.

To use it, simply add the header file as normal:

#import <Foundation/Foundation.h>
#import "CompassPoint.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        for (CompassPoint *point in CompassPoint.values) {
            if (point == CompassPoint.North) {
                NSLog(@"direction is north");
            }
            else if (point == CompassPoint.South) {
                NSLog(@"direction is south");
            }
            else if (point == CompassPoint.East) {
                NSLog(@"direction is east");
            }
            else if (point == CompassPoint.West) {
                NSLog(@"direction is west");
            }
        }
    }

    return 0;
}

objc

If you set your “Output Files” to be ${DERIVED_FILE_DIR}, the header paths have no trouble finding the generated header.

Step 4: Handling Build Errors Of course, sometimes you might make a mistake in your .prot file. It would suck if there was no way to handle this or to be notified of this… but of course that’s not the case!

Change your .prot file to this:

enum CompassPoint North | South | East | West

Notice the missing : between CompassPoint and North. Re-build your project, and voila!

Errors are reported and clickable!

: .caption

Not only can the error be reported, but it will cause your project to report a build failure. Those errors are also linked back to your source, so double-clicking will open your .prot file and show the error there.

Pretty cool.

The only missing thing is code completion and colorization. Unfortunately, to the best of my knowledge, those two features require full-blown Xcode plug-ins – way out of scope for this blog entry.

Next Steps Over the years, Objective C has attempted to get facelifts. Way back the 1997 timeframe, there was a project to create a “modern syntax” for ObjC. It didn’t go well. Then there was the ObjC-Java bridge that came in 2001. That also didn’t go well.

However, in 2006 we got ObjC 2.0. That was pretty good step forward for the Objective C language. And of course, in 2014, we got Swift.

I think the biggest disservice we can do to the Cocoa developer community is remove the underpinnings of the ObjC runtime. It is the language’s, and I truly believe, the platforms’ greatest strength.

I believe if we hide the complexities of C from our source code and focus on letting the power of the ObjC runtime shine through in our code, we can create a new language that provides of the great flexibility of the ObjC runtime while still accomplishing many of the goals that Swift is attempting to solve – namely safer code by default.

So I guess this is the start of the project I’m calling Proteus. We’ll see how far it gets.

  1. Note that you can put labels here in Swift as well, they just are not required.
  2. Now, we could go the extra mile on step #2 and simply emit the LLVM code, but honestly, I don’t have time to go down that route. It’s also not necessary for what I want to accomplish here.
  3. Here’s the repo link for the state at the time of authoring this blog entry: https://github.com/owensd/proteus/tree/78d0b2ad729948fcef7e6da80e966574b372cc91.
Building a Better Objective C

Building Swift-Style Enums in ObjC, Part 3

You can find part 1 and part 2 if you need to catch up. This part will be about creating Swift’s “raw value” enum type.

Feature Set This is essentially the same as the “traditional” enum with additional piece: a specific value for the given enum value. The requirements are simple:

  1. Each value represents a unique option
  2. Each value has an intrinsic value

Swift Examples This is what the Swift code looks like:

enum ASCIIControlCharacter: Character {
    case Tab = "\t"
    case LineFeed = "\n"
    case CarriageReturn = "\r"
}

swift

You assign one like this:

var controlCharacter = ASCIIControllCharacter.Tab

And you use it like this:

switch controlCharacter {
case .Tab:
    println("this is a tab")
case .LineFeed:
    println("who doesn't love newlines?")
case .CarriageReturn:
    println("notepad needs these... don't forget!")
}

ObjC Usage Let’s start with how we use it. First, how we declare it:

ASCIIControlCharacter *controlCharacter = ASCIIControlCharacter.Tab;

Like the previous examples, the switch-statement needs to be converted to an if-statement.

ASCIIControlCharacter *controlCharacter = [ASCIIControlCharacter fromRaw:@"\t"];
if (controlCharacter == ASCIIControlCharacter.Tab) {
    NSLog(@"this is a tab");
}
else if (controlCharacter == ASCIIControlCharacter.LineFeed) {
    NSLog(@"who doesn't love newlines?");
}
else if (controlCharacter == ASCIIControlCharacter.CarriageReturn) {
    NSLog(@"notepad needs these... don't forget!");
}

objc

There is a bit less typing in the Swift version, but not much1.

ObjC Implementation Now is time for the dreaded implementation… it’s always much more painful in ObjC.

@interface ASCIIControlCharacter : NSObject

@property (copy) NSString *rawValue;

- (instancetype)initWithCharacter:(NSString *)rawValue;

+ (ASCIIControlCharacter *)Tab;
+ (ASCIIControlCharacter *)LineFeed;
+ (ASCIIControlCharacter *)CarriageReturn;

+ (ASCIIControlCharacter *)fromRaw:(NSString *)rawValue;

@end

@implementation ASCIIControlCharacter

#define RETURN_ENUM_INSTANCE(CHAR) \
    static ASCIIControlCharacter *instance = nil;\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
        instance = [[ASCIIControlCharacter alloc] initWithCharacter:CHAR];\
    });\
    return instance;

+ (NSMutableDictionary *)rawLookup;
{
    static NSMutableDictionary *lookup = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        lookup = [[NSMutableDictionary alloc] init];

        [lookup setObject:ASCIIControlCharacter.Tab forKey:@"\t"];
        [lookup setObject:ASCIIControlCharacter.LineFeed forKey:@"\n"];
        [lookup setObject:ASCIIControlCharacter.CarriageReturn forKey:@"\r"];
    });

    return lookup;
}

- (instancetype)initWithCharacter:(NSString *)rawValue
{
    if (self = [super init]) {
        self.rawValue = rawValue;
    }
    return self;
}

+ (ASCIIControlCharacter *)Tab              { RETURN_ENUM_INSTANCE(@"\t"); }
+ (ASCIIControlCharacter *)LineFeed         { RETURN_ENUM_INSTANCE(@"\n"); }
+ (ASCIIControlCharacter *)CarriageReturn   { RETURN_ENUM_INSTANCE(@"\r"); }

+ (ASCIIControlCharacter *)fromRaw:(NSString *)rawValue
{
    return ASCIIControlCharacter.rawLookup[rawValue];
}

@end

So yeah… without doing anything magical, the straight ObjC version is not so awesome to author compared to the Swift version. It is more flexible, but much more verbose.

The root of the problem is not the inability for ObjC to express these types, it’s simply the ease in which ObjC can do it.

It’s about the syntax. And we’re getting there… =)

  1. If we wanted, we could even set it up so that the ObjC version could hold different types of raw values; that’s something that’s not possible in Swift today.
Building Swift-Style Enums in ObjC, Part 3

Building Swift-Style Enums in ObjC, Part 2

In the previous article, I took a look at building “traditional” enums from Swift into ObjC. This time, we’ll take a look at how we might build the “associative value” enum.

Feature Set

Swift also allows you to create “enum” values that are able to store various pieces of data stored alongside that enum value. The requirements are essentially this:

  1. Store associated values of any given type
  2. The value types can be different for each member of the enumeration

Swift Examples

In Swift, one such enum might look like this:

enum Barcode {
    case UPCA(Int, Int, Int, Int)
    case QRCode(String)
}

swift

You create one like this:

var productBarcode = Barcode.UPCA(8, 85909, 51226, 3)

And you use it like this:

switch productBarcode {
case .UPCA(let numberSystem, let manufacturer, let product, let check):
    println("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
case .QRCode(let productCode):
    println("QR code: \(productCode).")
}

swift

Essentially what you are creating is a set of classes that hold data grouped under a Barcode namespace. We can do something similar in ObjC.

ObjC Usage

Let’s start with how we use it. First, how we declare it:

Barcode *productBarcode = [Barcode UPCA:8 :85909 :51226 :3];

Pretty similar to Swift, not too bad.

And how about that switch-statement? Well, we can do it with an if-statement instead:

if ([productBarcode isKindOfClass:[UPCA class]]) {
    NSLog(@"UPC-A: %ld, %ld, %ld, %ld", [(UPCA *)productBarcode part1],
                                        [(UPCA *)productBarcode part2],
                                        [(UPCA *)productBarcode part3],
                                        [(UPCA *)productBarcode part4]);
}
else {
    NSLog(@"QR code: %@", [(QRCode *)productBarcode part1]);
}

objc

Ok, the ObjC version is starting to look ugly again because of a syntax problem; we cannot pull out the components and nicely as we can in Swift… but we’ll address that later too.

ObjC Implementation

Ok… so how do we implement this in ObjC? Well, remember, this is really just a special type that is getting returned depending on which “enum” value you want.

@class UPCA;
@class QRCode;

@interface Barcode : NSObject

+ (UPCA *)UPCA:(NSInteger)part1 :(NSInteger)part2 :(NSInteger)part3 :(NSInteger)part4;
+ (QRCode *)QRCode:(NSString*)barcode;

@end

@interface UPCA : Barcode
@property (assign) NSInteger part1;
@property (assign) NSInteger part2;
@property (assign) NSInteger part3;
@property (assign) NSInteger part4;
@end

@interface QRCode : Barcode
@property (copy) NSString *part1;
@end

@interface UPCA (Private)
- (instancetype)initWith:(NSInteger)part1 :(NSInteger)part2 :(NSInteger)part3 :(NSInteger)part4;
@end

@interface QRCode (Private)
- (instancetype)initWith:(NSString *)part1;
@end

@implementation Barcode

+ (UPCA *)UPCA:(NSInteger)part1 :(NSInteger)part2 :(NSInteger)part3 :(NSInteger)part4
{
    return [[UPCA alloc] initWith:part1 :part2 :part3 :part4];
}

+ (QRCode *)QRCode:(NSString*)barcode
{
    return [[QRCode alloc] initWith:barcode];
}

@end

@implementation UPCA

- (instancetype)initWith:(NSInteger)part1 :(NSInteger)part2 :(NSInteger)part3 :(NSInteger)part4
{
    if (self = [super init]) {
        self.part1 = part1;
        self.part2 = part2;
        self.part3 = part3;
        self.part4 = part4;
    }

    return self;
}

@end

@implementation QRCode

- (instancetype)initWith:(NSString *)part1
{
    if (self = [super init]) {
        self.part1 = part1;
    }

    return self;
}

@end

objc

WOW! That is a ton of boiler-plate code. But we are there, we have the same functionality that we have in Swift. Would you I want to write this? Eh… no. But, the point here is just to see how we might implement these features from Swift in ObjC directly. There are of course many optimizations we can do and generalizations to make; this is only one naïve implementation of “associated values”.

More next time.

Building Swift-Style Enums in ObjC, Part 2

Building Swift-Style Enums in ObjC, Part 1

I thought it would be an interesting thought experiment if we take a look at features that are present in Swift and see what it would take to build them out in ObjC.

Up on the docket today is the Enum. Of course, Swift really supports three different types of enums:

  1. The "traditional" enum — simply a list of potential options
  2. An "associated value" enum — enums with particular values that can be held but grouped under a context
  3. The "raw value" enum — an enum that stores a specific value for each of the options.

In this post, we'll be looking at the "traditional" enum.

Feature Set

So the traditional enum is quite basic and needs only to implement the following rules:

  1. Each value represents a unique option
  2. There is no intrinsic value to any given option

Optionally, it would be nice to be able to:

  1. Iterate over all of the options
  2. Know the number of options available

Implementation There are a couple of options available to us:

  1. Use the C-style enum that is already supported in ObjC
  2. Build the enum using @interface (e.g. classes)

I'll be going with option #2 as it provides the most flexibility and allows us to be true to all of the rules.

I'll be creating the CompassPoint enum from the Swift language guide.

enum CompassPoint {
    case North
    case South
    case East
    case West
}

swift

In ObjC, we need to have the following:

@interface CompassPoint : NSObject

+ (CompassPoint *)North;
+ (CompassPoint *)South;
+ (CompassPoint *)East;
+ (CompassPoint *)West;

@end

#define RETURN_ENUM_INSTANCE() \
    static CompassPoint *instance = nil;\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
        instance = [[CompassPoint alloc] init];\
    });\
    return instance;

@implementation CompassPoint

+ (CompassPoint *)North { RETURN_ENUM_INSTANCE(); }
+ (CompassPoint *)South { RETURN_ENUM_INSTANCE(); }
+ (CompassPoint *)East  { RETURN_ENUM_INSTANCE(); }
+ (CompassPoint *)West  { RETURN_ENUM_INSTANCE(); }

@end

objc

Well… that's looking a bit ugly, but we've met the initial requirements.

Usage of the enum is almost identical to Swift, with two caveats:

  1. Unable to use the shorter dot-notation
  2. Unable to use the switch-statement

Here's what the usage code looks like:

CompassPoint *directionToHead = CompassPoint.South;
if (directionToHead == CompassPoint.North) {
    NSLog(@"Lots of planets have a north");
}
else if (directionToHead == CompassPoint.South) {
    NSLog(@"Watch out for penguins");
}
else if (directionToHead == CompassPoint.East) {
    NSLog(@"Where the sun rises");
}
else if (directionToHead == CompassPoint.West) {
    NSLog(@"Where the skies are blue");
}

objc

The nice thing about this ObjC version is that it's quite easy to add some additional functionality, like the ability to iterate over all of the values:

@interface CompassPoint (Iteration)
+ (NSArray *)allValues;
@end

@implementation CompassPoint (Iteration)
+ (NSArray *)allValues
{
    static NSArray *values = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        values = @[ CompassPoint.North, CompassPoint.South, CompassPoint.East, CompassPoint.West ];
    });

    return values;
}

@end

Obviously the syntax for the ObjC sucks, especially in comparison to what we get in Swift. There are lots of different options available for us to make this better in ObjC, but more on that later.

Building Swift-Style Enums in ObjC, Part 1