[Swift] Objective-CとSwiftの共存と相互連携

written: kengo
tag:

SwiftからObjective-Cの内容をコールにするには、Bridge Fileを用意することで容易に連携できます。例えば、Objective-Cで作成したHogeクラスをSwiftで使う場合、次のような感じになります。

Hoge.h

#import <Foundation/Foundation.h>
 
@interface Hoge : NSObject
-(void) hogehoge;
@end

Hoge.m

#import "Hoge.h"
 
@implementation Hoge
-(void) hogehoge
{
    NSLog(@"ほげほげ");
}
@end

****-Bridge.h

#import "Hoge.h"   // HogeをSwiftにブリッジ

main.swift

import Foundation
 
var h = Hoge()    // Obj-CのHogeの実体を生成
h.hogehoge()      // Obj-Cのhogehogeメソッドをコール
 
exit(0)

Obj-Cのあるプロジェクト内でSwiftファイルを新規作成しようとすると「ブリッジファイルを作りますか?」と聞かれるのでYesにしておくと***-Bridge.hが自動生成(&プロジェクト設定)がなされるので、便利で楽ちんです。上記の例ではmain.swiftを作っていますが、iOS開発ならばAppDelegateのapplicationLaunch…のメソッド内でHogeを使ってみるといいと思います。

SwiftとObj-Cに同じ名前の型を定義する(Swift1.2)

自作例ですが、Swiftを含むフレームワークを作るとき、ObjCで記述できないものをSwiftで書くため、同名クラスがフレームワーク内に2つできることになりました(SwiftのHogeとObjCのHoge)。

これちゃんと動くのかな?と心配になりましたが、結論から言うとSwiftのHogeが、何のクラスも継承していない(厳密にはObjCのクラスを継承していない)状況であれば、同じフレームワーク内に入れることができました。

上記とは逆にSwiftのクラスをObjCに連携するために、Bridgeとは逆の***-Swift.hというファイルが生成されます。ここにSwiftのクラスがObjC用に変換されて自動で追加されます。このとき追加される条件が、NSObjectの派生クラスであることで、NSObjectの派生でなければ、連携されない、ということにもなります。よって制限はありますが2つの同名クラスをObjC, Swiftで記述して使い分けることもできるようです。

とはいえ、Swiftに統一したほうが良い感触

ただ上記のクラスの話はとてもニッチな話で、できるだけSwiftで書いたものをObjCで共有する方向性でまとめたほうがいい気がします。書いてみた感覚からして継承の不自由がありますし。