Blog

Swift extensions over pragmas

The #pragma preprocessor directive is a C standard defined as a way to provide information to the compiler. The original purpose was to make source code portable between different compilers but it is possible to use it for other things. For instance in C++ #pragma once is a commonly used directive to act as an include guard and In C we can use it to inhibit warnings with #pragma clang diagnostics.

In Objective-C we use the #pragma directive a bit differently.

Pragmas in Objective-C

At ustwo we use #pragma mark to organize the code in sections. We divide each section by functionality which makes the code a lot easier to read and we also get the visual representation in the Xcode source navigator. We also group all the methods for each protocol with a #pragma mark.

A simple UIViewController that conforms to the UITableViewDataSource and UITableViewDelegate protocols would look like this:

@implementation ViewController#pragma mark - UITableViewDataSource- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return [self.items count];}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ return [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];}#pragma mark - UITableViewDelegate- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ // Navigate to item details}@end

Pragmas in Swift

As described earlier the #pragma directive is a C preprocessor and because Swift is built without the constraints of C we cannot use #pragma mark in our Swift code.

However there is a replacement that can be used to group your code in to sections: // MARK:. Unfortunately this is not implemented yet in the current version of Xcode but engineers at WWDC said it will be available in a future release.

In Swift the same example as above would look like this when we use // MARK:

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { // MARK: UITableViewDataSource func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> \ Int { return items.count } func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { return tableView.dequeueReusableCellWithIdentifier(CellIdentifier, forIndexPath: indexPath) } // MARK: UITableViewDelegate func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) { // Navigate to item details }}

Extensions

By comparing the two examples above I feel the // MARK: directive is not as clean as #pragma mark. When using #pragmas I see it as a header for each of my groups in the code but when using // MARK: I can only see an empty comment. It doesn’t feel like a header for my group.

That got me thinking that there has to be another way to divide my code in groups and when I was reading about extensions in The Swift Programming Language book I found this:

You can use an extension to add protocol conformance to a type that is declared elsewhere, or even a type that you imported from a library or framework.

What this means is that instead of dividing the code in my class in groups with headers I can extract that specific code in to an extension.

Meaning we will isolate the code that is conforming to a specific protocol. We can also put code that is related to the same functionality in its own extension.

Lets look at the same example as before when we have extracted the protocol conformance in an extension:

class ViewController: UIViewController {}extension ViewController: UITableViewDataSource { func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { return items.count } func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { return tableView.dequeueReusableCellWithIdentifier(CellIdentifier, forIndexPath: indexPath) }}extension ViewController: UITableViewDelegate { func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) { // Navigate to item details }}

Not only does this give me a nice separation of code but I also get my extensions to look like single protocol conformance!

We have probably all seen something similar to this:

MyAmazingViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UIScrollViewDelegate, UIActionSheetDelegate, UIAlertViewDelegate, MyCustomControlDataSource, MyCustomControlDelegate>

One can argue that this is too much work for a single ViewController and the functionality should be split up. But these monsters still exist out there!

If, or when you are porting your app to Swift, think about what you can do with extensions. It is very powerful and your AmazingViewController could be split up in a more readable and more organized way if you extend your class with each protocol it conforms to.

Further discussions

We have been trying out this approach quite a lot when we are porting our apps and one drawback that we have found is that you cannot name your extensions without using a typealias.

A solution to that could be to put your extensions in separate files with a name that explains what it is doing.

How would you do it?

Would you use extensions as the examples above? Would you put them in the same file together with the class or in separate files?

I would love to hear your thoughts!