こんにちは。モバイルファースト室の中村です。
仕事でSwiftを使うことはまだないのでSwiftについて色々気になっている今日この頃です。
今回はSwiftとObjective-C(以下、Obj-C)を1つのプロジェクト内でつかう方法と、両者の相違点について気になった点を紹介したいと思います。
Swift -> Obj-C
まず、SwiftからObj-Cを使う方法です。
SwiftからObj-Cを使うには、[product module name]-Bridging-Header.hを作成します。
※ [ProductModuleName]は通常ProductNameと同じです。ProductNameにアルファベット以外の文字を使っている場合、その文字は( _ )(アンダースコア)に置換されます。
Xcodeのメニュー"File > New > File > (iOS or OS X) > Source > Header File."からファイル名を[product module name]-Bridging-Header.hと指定しプロジェクトに追加します。
このBridging Header Fileに、SwiftからインポートしたいObj-Cヘッダーファイルを書きます。
// SwiftAndObj_C-Bridging-Header.h #import "XYZCustomViewController.h"
Build Settings > Objective-C Bridging Headerに作成したファイルのパスを指定します。
これでBridging header fileに書かれたObj-Cヘッダーファイルが、全てのSwiftファイルから見えるようになりました。
次のようにSwiftからXYZCustomViewControllerのインスタンスが作成できます。
Swift var controller = XYZCustomViewController() self.view.addSubview(controller.view)
Obj-C -> Swift
今度は逆に、Obj-CからSwiftを使う方法です。
Obj-CからSwiftをつかうには、次のインポート文を書きます。
Obj-C #import [ProductModuleName]-Swift.h
※ [ProductModuleName]-Swift.hファイルはXcodeから自動生成されるもので、開発者が用意する必要はありません。
これでObj-CからSwiftを使うことができます。
Obj-C #import "SwiftAndObj_C-Swift.h" // ViewControllerクラスがSwiftで書かれている場合 ViewController* controller = [ViewController new]; controller.view = [self configureView:controller.view];
型の違い
Obj-Cの変数をSwiftで使う場合、両者の型が違うのでコンバージョンやダウンキャストをします。
// CGFloatをFloat型に代入するには、コンバージョンしたい変数を括弧で囲みコンバージョンします。 myFloat = Float(controller.cgfloat)
// NSDictionaryをDictionaryに、NSArrayをArrayに代入するにはas演算子でダウンキャストします。 myDictionary = controller.nsdictionary as Dictionary<String , AnyObject> myArray = controller.nsarray as Array<AnyObject>
デリゲートパターン
Obj-Cではデリゲートオブジェクトに対してメッセージ送信可能かrespondsToSelector:
メソッドで確認後メッセージ送信していました。
Swiftではif-let
シンタックスで次のようにスッキリと書けます。
Obj-C if ([self.delegate respondsToSelector:@selector(delegateMethod:)]) { [self.delegate delegateMethod:arg]; }
Swift if let value = delegate?.delegateMethod?(arg) { println(value) }
?演算子でデリゲートがnilかどうか、メソッドが定義されているかどうかチェックしています。
キー値監視
NSObjectを継承して作成したSwiftクラスは、キー値監視が使えます。監視したいプロパティにdynamic修飾子を追記します。
Swift class MyObjectToObserve: NSObject { // dynamic修飾子を追記します dynamic var myDate = NSDate() func updateDate() { myDate = NSDate() } } class MyObserver: NSObject { private var myContext = 0 var objectToObserve = MyObjectToObserve() override init() { super.init() objectToObserve.addObserver(self, forKeyPath:"myDate", options: .New, context: &myContext) } override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject: AnyObject], context: UnsafeMutablePointer<Void>) { if context == &myContext { println("Date changed") } else { super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) } } deinit { objectToObserve.removeObserver(self, forKeyPath: "myDate", context: &myContext) } }
まとめ
Obj-CとSwiftを同時に使う方法と、両者の相違点について書きました。この記事は、Using Swift with Cocoa and Objective-Cから気になった箇所を紹介させていただきました。 iBooks Storeで無料でダウンロードできるので、もしまだという方は1度目を通してみると良いかと思います。