lunedì 12 gennaio 2015

A step-by-step way to port Objective C classes to swift (part 1)

As many programmers around the world i was very pleased at the announce of the new swift language. I started with some sample code and i liked it so much that i wanted to use it in my production projects (even if in beta and often changing, even if not well documented...).
Mixing Objective C and swift code in the same project is quite easy, but when you want to use the most juicy features of swift like enums or generics you start writing a growing section of your project with not-objective-c-accessible code.

This grow up to a point where your old classes need to be rewritten in swift. Tedious and boring, but beneficial to the project.

My experience was that i needed to develop a standard and basically mechanical procedure to go from "@interface MyClass" to "class MyClass", mantaining all the old features and a compiling application, with the benefit of adding the swift compatibility.

Without further ado here is my list, feel free to adapt it to your situation and comment with the needed changes.

Suppose you want to migrate the class MyViewController from Objective c to swift

*) Take your application to a compiling and running state. 
If you have unit tests make sure they all pass or at least the ones related to the class that you want to rewrite. If applicable add a couple of unit tests for the class.
Run your program and note down what works and what don't.

Your current objective is not to fix bugs, it is only to rewrite the same code in swift, with the same bugs. One thing at a time!

*) Include the objective-c class header in your ${project}-bridging-header.h. 
Build, test, run.

*) Create a SwiftMigrations swift class. In my case i just created one for the whole project, but you could prefer to make one for every migrating classes.
This class will be marked @objc or inherit from NSObject, because you will need to call its methods from Objective C code. 
Build, test, run and commit.

*) Now choose one of the methods in your objective c class. The perfect candidate is one from which you would like to access some beautiful new swift-only code, like enums or generics.
So for example you did chose the method 
-(void)viewDidLoad {}
In the SwiftMigrations class you will add this method:
class func MyViewController_viewDidLoad(mvc:MyViewController) {}

*) Go on writing the swift implementation of the all method, using the mvc argument where you would use self.

*) In the objective-c class just comment the old method implementation and delegate to the new implementation like this:

-(void)viewDidLoad
{
    [SwiftMigrations MyViewController_viewDidLoad:self];
}

Build, test, run and commit.


Chances are that you are already happy with this; it's not pretty, but it allows you to use swift-only features from your old class.