Wednesday, August 26, 2015

Integrating Swift with Objective C

I started to implement the new design for Jano (Japano) and I decided to do some small refactoring of the code.

In the Achievements screen I am displaying a list of levels that the user can achieve by taking tests in a UIScrollView. It's a maximum of 4 levels and each of the views needs to have a background image.

Initially I subclassed UITableViewCell and I wrote the code inside the class for the arranging of the GUI elements.
Now I want to use another class that will take care of the GUI only. I will do this using Swift and in this post I will write about how to combine the two types of files.

First thing, add a new file from the menu File - New - File and select Swift File. After naming it, Xcode will ask you if you want to add bridging header. Click Yes.

I have named the class LevelCellInterfaceTool. By default the class is not public, so I had to modify the access level of the class to public:


public class LevelsCellInterfaceTool: NSObject {

}
Inside the class I then created a public method (func) that just shows a simple UIAlertView:

public class LevelsCellInterfaceTool: NSObject {
public func ShowSimpleMessage()
    {
        let message = "This is a UIAlerView declared in Swift!"
        let v = UIAlertView(title: "Swift UIAlertView", message: message, delegate: nil, cancelButtonTitle: "Ok")
        v.show()
    }

}
The next challenge was to call ShowSimpleMessage from a class declared in an Objective C file (.h and .m). This was accomplished in 3 simple steps:

1. Forward declare LevelCellInterfaceTool in the interface file (.h) of the class that needs it: 
@class LevelsCellInterfaceTool;

@interface LevelsListCellTableViewCell : UITableViewCell

{
        
}

@end

2. In the implementation file (.m) use an #import directive for all the classes declared with Swift. In the official documentation it is saying to use a particular naming convention: ProductModuleName-Swfit.h.
In my case, ProductModuleName is the name of the project. So, it becomes Jano-Swift.h:

#import "LevelsListCellTableViewCell.h"
#import "Jano-Swift.h"

@implementation LevelsListCellTableViewCell
...
@end

3. Calling the method.
After writing a new method (func) in the Swift class it is necessary to first build the project so that the Objective-C class sees it (at least in Xcode 6.3.2).
Somewhere in the class instantiate the Swift class as you would with a regular Objective-C class:

LevelsCellInterfaceTool *guiTool = [[LevelsCellInterfaceTool alloc] init];
        [guiTool ShowMessage];
        [guiTool release];