Swift brings lots of awesome new features. I’m looking forward to using lots of them, even though it’s still a bit early for me to adopt the language. Even if you don’t want to or can’t adopt the new language yet, you should still be able to get your hands on the new features that they’ve created, like value types, richer enums, and protocol extensions. In some cases, you might even want to be able to experiment and get access to these features even before Apple announces them.

Luckily for us, a language that’s rich enough lets us approximate these features. In the immortal words of Kanye West, “everything in the world is exactly the same.” Let’s take a look at a few ways how we can get Swifty features in Objective-C.

Value Types

The first awesome Swift feature we want to examine is the Swift struct and its value semantics. To know how to replicate this feature in something like Objective-C, we need to first figure out how we use it and which parts of the feature we want.

Unfortunately, developing this distinction between inert values and living, breathing instances isn’t easy. Via the Swift book:

As a general guideline, consider creating a structure when one or more of these conditions apply:

  • The structure’s primary purpose is to encapsulate a few relatively simple data values.
  • It is reasonable to expect that the encapsulated values will be copied rather than referenced when you assign or pass around an instance of that structure.
  • Any properties stored by the structure are themselves value types, which would also be expected to be copied rather than referenced.
  • The structure does not need to inherit properties or behavior from another existing type.

My general criterion is if you don’t care which copy of a thing you have, it’s a value.

So, given that description of values, we primarily want to take advantage of their immutability and isolation. (There are some slight performance gains as well, but come on — profile before optimizing.)

For a mutable thing to cause unintentional bugs in your app, it must also be accessed from more than one place; after all, if it’s only every used in one place, it can’t change out from under you. Structs in Swift solve this problem by either being immutable, in which case you can’t change them, or being copy-on-mutate: as soon as you change one, you get a fresh copy that’s yours and yours alone.

To get the same benefit, we need to either preserve either the immutability of our object or its isolation. To preserve isolation in Objective-C, we can conform to NSCopying and declare all properties as copy. This is pretty tedious and it’s easy to forget to copy every time you use the object in a new place.

Immutability, on the other hand, is all defined in the class’s interface, and lets us give the class’s users hints about how the class should be used.

In The Value of Value Objects, I write about using a pattern called Tiny Types (gist) to get immutable wrappers around values.

@interface Hostname : ValueObject

- (instancetype)initWithString:(NSString *)name;

@property (readonly) NSString *name;  
@property (readonly) NSURL *hostnameAsURL;  
@property (readonly) Hostname *hostnameByEnsuringSSL;

@end

@implementation Hostname

- (instancetype)initWithString:(NSString *)name {  
	return [self initWithBackingObject:name];  
}

- (NSString *)name {  
	return self.backingObject;  
}

- (NSURL *)hostnameAsURL {  
	return [NSURL URLWithString:self.name];  
}

- (Hostname *)hostnameByEnsuringSSL {  
	NSURLComponents *URLComponents = [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:YES];  
	URLComponents.scheme = @"https";  
	return [[Hostname alloc] initWithString:URLComponents.URL.absoluteString];  
}

@end  

Because this object isn’t mutable, you never have to worry about it changing out from underneath you. Even when it does need to be changed, as in -hostnameByEnsuringSSL, it returns a new Hostname object, never changing the existing one.

In the same way that Swift’s compiler enforces proper behavior, so too does Objective-C’s. With a message like -hostnameByEnsuringSSL, the name and its type signature make it clear that something different is happening, and that you need to handle it in a special way.

This pattern can be extended to allow intialization with multiple “backing objects” rather than just one, but the principles (immutable properties and copy-on-mutate) stay the same.

Rich Enumerations

Swift’s enums are a great step forward from C’s enumerations. The greatest advantage is that you can associate both data and functions with the enum now. In the old C-style, enumerations were nothing more than some sugar around a number:

typedef enum Shape : NSUInteger {  
	Circle,  
	Rectangle  
} Shape;  

To do work with these, you have to pass them into a top-level or free function:

NSInteger calculateArea(Shape s);  

Reversing the subject and object like this is harder to read, for some reason, and no one likes it.

Swift allows us to describe create an enum more easily, associate data with it (such as the radius or width and height below). Once we have data, we can add behavior as well:

enum Shape {  
	case Circle(Double)  
	case Rect(Double, Double)

	func area() -> Double {  
		switch self {  
		case let Circle(r):  
			return pi * r * r  
		case let Rect(width, height):  
			return width * height  
		}  
	}  
}  

Ultimately, though, these enumerations are all “sum types”, or tagged unions. They can be in one of many disjoint states. Fortunately for us, sum types can take many forms, and we have access to some of them in Objective-C. If we want a sum type with associated data and functions, just like Swift’s, we can easily get that.

@interface Shape : NSObject

@property NSInteger area;

@end

@implementation Circle : Shape

- (instancetype)initWithRadius:(NSinteger)radius {  
	self = [super init];  
	self.radius = radius;  
	return self;  
}

- (NSInteger)area {  
	return M_PI * self.radius * self.radius;  
}

@end  

Here, instead of an enum called Shape, we have an abstract class called Shape, and several concrete classes that derive from it, defining their own initializers and bringing their own implementations for -area.

There’s a caveat here, which is that this solution uses inheritance. However, this is something I’d call “inheritance with intention”. It’s small, contained, and out of the way. The polymorphism defined early in the process, allowing it to be designed holistically. It lets other objects operate with less knowledge of how Shape works and minimizes fewer code paths. If it still bothers you, you can get the same “sum type” effect without inheritance by using protocols.

This pattern is discussion with more depth in Replace Enumerations With Polymorphism.

Protocol Extensions

Another big awesome feature in Swift is protocol extensions. I love this one and I feel like I’ve wanted it in Objective-C forever. At its core, protocol extensions add extra behavior to an abstract set of messages. I’ve been leaning very heavily on decoration to get the same thing (behavior added to a preexisting thing) when I’m in Objective-C.

Let’s look at an example. A data source object helps you map index paths to objects, so that they can be displayed in a table view or collection view. A protocol for a data source might be defined like so:

@protocol DataSourceProtocol

@property NSInteger numberOfSections;  
- (NSInteger)numberOfObjectsInSection:(NSInteger)section;  
- (id)objectAtIndexPath:(NSIndexPath *)indexPath;

@end  

This is the bare minimum we need to implement this protocol. If we were in Swift and we wanted to add any functions whose results were derived from these, we could use protocol extensions. In Objective-C, however, we’ll use decoration:

@implementation FullDataSource

- (instancetype)initWithDataSource:(id<DataSourceProtocol>)dataSource { //... }

//forward -numberOfSections, -numberOfObjectsInSection: and -objectAtIndexPath: to self.dataSource

- (NSArray *)allObjects {
    NSMutableArray *allObjects = [NSMutableArray array];
    NSInteger numberOfSections = self.numberOfSections;
    for (NSInteger sectionIndex = 0; sectionIndex < numberOfSections; sectionIndex++) {
        NSInteger numberOfObjectsInSection = [self numberOfObjectsInSection:sectionIndex];
        for (NSInteger objectIndex = 0; objectIndex < numberOfObjectsInSection; objectIndex++) {
            [allObjects addObject:[self objectAtIndexPath:[NSIndexPath indexPathForRow:objectIndex inSection:sectionIndex]]];
        }
    }
    return allObjects;
}

- (NSIndexPath *)indexPathForObject:(id)object {
    for (NSInteger sectionIndex = 0; sectionIndex < self.numberOfSections; sectionIndex++) {
        NSInteger numberOfObjectsInSection = [self numberOfObjectsInSection:sectionIndex];
        for (NSInteger objectIndex = 0; objectIndex < numberOfObjectsInSection; objectIndex++) {
            id object = [self objectAtIndexPath:[NSIndexPath indexPathForRow:objectIndex inSection:sectionIndex];
            if ([object isEqual:object]) {
                return object;
            }
        }
    }
    return nil;
}

@end

By wrapping a DataSourceProtocol in DataSource, we can add behavior to any data source defined with that protocol, like -allObjects and a reverse lookup method called -indexPathForObject:. We could also add a method to enumerate over the objects with a block, and so on.

Whereas with the enumeration example we had caveats, here we have two major advantages. First, decoration can be done multiple times. If you want to wrap a wrapped thing, you can do that. Second, you gain the ability to change which decorators you are using dynamically. Some DataSourceProtocol objects need some decorators, and others need different ones. You can mix and match them however you like.

Conclusions

I’ve written about all these patterns here with more depth: value objects here, enumerations here, and decoration here, here, here, and here. Yes, Swift allows you to express these ideas much more tersely, and in some cases, prevents you from making errors while expressing them. This is to Swift’s benefit. These ideas are more flexible than their specific implementations in Swift, however. As you implement them, you get to decide exactly how they work.

It’s also notable that the blog posts describing these patterns came out before their respective Swift counterparts. If you’re willing to bend the traditional uses of the language a little, and you can reap their benefits, and you can do it before everyone else. Don’t wait for anyone. Write your own future.