衝撃のSwift発表からもうすぐ1年……。
遅まきながら既存のObjective-Cソースコードをマイグレーションしようとしていたら
アップル様が素晴らしいガイド(Migrating Your Objective-C Code to Swift)を公開されていたので
補足情報を交えつつおっかなびっくり和訳してみます。
※投稿主は,そんなに英語が達者ではありません。(と予防線を張っておく)
マイグレーションを始める前に
1. 既存のObjective-Cに対応するSwiftクラスを作成する
Objective-Cの.hと.mファイルに対応する.swiftファイルをXcodeから作成します。
(File > New > File > (iOS or OS X) > Source > Swift File)
クラス名については既存ソースと同じでも構いませんし,変えてもOKです。
ちなみに,Objective-Cであったプレフィックス(NSほにゃらら,UIほにゃらら)を付けるかどうかは自由です。よしなに。
2.フレームワークをインポートする
必要なフレームワークを適宜インポートします。
例えば,UIViewControllerサブクラスではUIKitをインポートするとか。
3. [オプション] SwiftからObjective-Cを呼び出すためのBridging Headerを作成する
ソースコードをすべてSwiftに置き換えるならば,この手順は必須ではありません。
SwiftからObjective-Cのソースコードを呼び出す必要がある場合,Bridge Headerファイルを作成します。
(Bridge Headerファイルは,SwiftプロジェクトにObjective-Cのソースコードを追加すると作成された気がします)
詳細については,Importing Code from Within the Same App Targetを参照。
4. [オプション]Objective-Cから呼び出されるための属性をSwiftクラスに追加する
ソースコードをすべてSwiftに置き換えるならば,この手順は必須ではありません。
Objective-CからSwiftのソースコードを呼び出す場合,以下のどちらかの方法で対応が必要です。
- Objective-Cが提供するクラスの子孫としてSwiftクラスを定義する
- Swiftクラスに@objc属性を付与する
前者は,例えばNSObjectのサブクラスとして定義する感じでしょうか。
NSObjectのサブクラスとして定義すると,前述のBridging Headerが生成されるようです。
後者はクラス定義時に@objc属性を追加するようです。
@objc class Party {
let name = "墓場鬼太郎"
}
こんな感じですね。
ちなみに@objc()という書き方をすれば,別の名前でクラスを参照可能です。
@objc(Utage)
class Party {
let name = "墓場鬼太郎"
}
@objcの詳細情報は,Swift Type Compatibilityを参照。
マイグレーション
1. Objective-Cでの振る舞いをSwiftの様式に変換する
クラス継承の方法やプロトコルの実装方法など,SwiftではObjective-Cと文法が異なるので,Swiftの流儀で書きなおしましょう。
Objective-Cの振る舞いをSwiftで再現する場合の参考情報は,Writing Swift Classes with Objective-C Behaviorです。
具体的には
- クラス継承
- プロトコル実装
- initializer
- deinitializer
- Interface Builderとの連携
- プロパティ定義
- CoreData連携
あたりがトピックで挙がっています。
2. SwiftがObjective-Cの機能をどのように扱うか理解する
Objective-Cの機能をSwiftがどのように扱うか知っておきましょう。
例えば,クラスの初期化についても,Swiftはallocが不要だったり,わざわざinitなんて書かなくて良いです。
同じクラスを利用する場合でもObjective-CとSwiftで扱い方が違うので差異を抑えておきましょう……ということですね。
詳細は,Interacting with Objective-C APIsを参照。
3. Objective-CとSwiftの変数型の対応関係を理解する
Cocoa FrameworkをSwiftから扱う場合,SwiftとObjective-Cの変数型のブリッジが行われることを覚えておく必要があります。
そのため,変数型がどのような対応関係になるのか知っておくことが重要です。
詳細は,Working with Cocoa Data Typesを参照。
一例としては,NSStringとStringの関係とか……ですかね。
4. デザインパターンを変換する
delegateやKVO,Target-Action,エラー通知などの一般的なデザインパターンもSwift流に書き換えましょう。
詳細については,Adopting Cocoa Design Patternsを参照。
上記の詳細ページには書かれていませんが
よく使うSingletonパターンも実装方法が変わるので書き換えが必要ですね。
5. プロパティ定義の変更が必要かどうか検討する
Swiftでは,Objective-Cよりもきめ細かくプロパティを定義出来ます。
例えば,@lazy属性を付与すれば遅延初期化といったことも可能になります。
Swiftの言語仕様を踏まえて,プロパティの定義を変更するかどうか検討します。
参考情報は,The Swift Programming Languageです。
6. プロパティや関数に別名を付けるかどうか検討する
必要に応じて,@objc()属性を付与することで,プロパティや関数に別名を付けられます。
var enabled: Bool {
@objc(isEnabled) get {
/* ... */
}
}
上記の例では,変数enabledのgetterメソッドにisEnabledという別名を付けています。
7. インスタンスメソッドとクラスメソッドをそれぞれ変換する
Objective-Cのインスタンスメソッド(-で定義)は,funcに変換します。
Objective-Cのクラスメソッド(+で定義)は,class funcに変換します。
8. マクロを変換する
単純なマクロは,グローバルな定数に変換します。
複雑なマクロは,関数に変換します。
マイグレーション後の作業
1. インポート文を書き換える
Objective-CからSwiftを呼び出す場合,Objective-C側のimport文を書き換えて,SwiftのBridge Headerクラスをインポートします。
詳細情報は,Importing Code from Within the Same App Targetを参照。
2. .mファイルをターゲットから外す
変換済みのObjective-Cの.mファイルをターゲットから外します。
(TargetのMembershipのチェックボックスを解除すればOK?)
あとでトラブルシュートで使うかもしれないので,.hと.mファイルは削除しないように!
3. 新しいSwiftクラスを使うようにコードを書き換える
Objective-C時代からクラス名が変わった場合,新しいクラスを使うように処理を書き換えます。
以上,多分に意訳を含んだり独自解釈盛り込んでますが,訳してみました。
Qiitaに初めて投稿するのでもっと見やすい書き方あったかもしれませぬ orz