SwiftとObjective-Cのコードを1つのプロジェクトでつかう

こんにちは。モバイルファースト室の中村(@_nkmrh)です。

仕事でSwiftを使うことはまだないのでSwiftについて色々気になっている今日この頃です。

今回はSwiftObjective-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"

f:id:nkmrh:20141202093827p:plain

Build Settings > Objective-C Bridging Headerに作成したファイルのパスを指定します。

f:id:nkmrh:20141202093936p:plain

これで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度目を通してみると良いかと思います。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/