特集
» 2015年08月06日 05時00分 UPDATE

iOSアプリ開発でObjective-CからSwiftに移行するための手順、注意点まとめ〜言語仕様の違いは? 連携時の呼び出し方は?

開発生産性や品質を向上させたいiOSアプリ開発者のためにObjective-CからSwiftへ移行するメリットや手順、注意点など勘所をまとめて紹介します。

[杉本裕樹,マネーフォワード]

そろそろ、Swiftへの移行を始める時期?

 iOSアプリ開発者の皆さま、もう「Swift」でアプリを開発していますか? 登場した日から一年以上たち、今はバージョン2.0のベータ版まで出ているプログラミング言語Swift。初期はコンパイルの遅さや不具合の多さが目立ったのですが、最近はその辺りの問題が解消されて非常に使いやすくなってきています。

 そろそろ、ぜひ移行をお勧めしたいのですが、既存のObjective-Cアプリを移行するのはなかなか大変な面もあると思います。チームで開発している場合は自分以外の開発者や関係者へ周知するコストも掛かりますし、Swiftへ移行する際のトラブルを思うと、いろいろな不安がつきまとうでしょう。

 本稿では、そういった不安が少しでも解消されるように、アプリ開発のプログラミング言語をObjective-CからSwiftへ移行するメリットや手順、注意点など勘所をまとめて紹介します。

 なお本稿は、SwiftやObjective-Cの書き方や言語仕様についてある程度分かっている方を対象読者としていますので、SwiftやObjective-Cの書き方や言語仕様について知りたい方は、下記連載などを参照してください。

Swiftへ移行するメリット――とにかく捗るSwift

 まずは、iOSアプリをSwiftで開発することによるメリットを紹介します。Swiftの長所はいろいろとありますが、大きく分けると下記の二つかと思います。

  • 厳密な言語仕様によるアプリの品質向上
  • モダンな構文による生産性向上

 以下でそれぞれについて説明していきます。

厳密な言語仕様によるアプリの品質向上

 Swiftは、「型が違うクラスへの代入禁止」「nilの扱いにおけるObjective-Cからの変化」によって厳密な言語仕様を持っています。

 特に「nilの扱いにおけるObjective-Cからの変化」はアプリ開発での不具合を大きく減らしてくれます。なぜならSwiftは、Objective-Cと違って、通常の変数がnilを持つことがないからです。Swiftの変数にnilを持たせたい場合は「Int?」などのように「?」を付けて「Optional(オプショナル)型」として定義する必要があります。これによって、変数に予想外の値が入る現象を減らせます。

 アプリを開発していると、nilが入らない想定の変数にnilが紛れ込むことで正しく動かない現象が起こります。特に、インスタンス変数のようにいろいろな箇所から参照される値はnilが紛れ込みやすいですし、どこで紛れ込んだかの特定が難しいです。

 しかしSwiftでは、オプショナル型以外にnilを入れた場合にはコンパイルできないので、そういった不具合も起きにくくなります。

let value: MyValue = nil // → コンパイルエラーになる
let value: MyValue? = nil // → エラーにならない

 他にも、「型が違う変数へキャストした場合に即時クラッシュする」「配列やディクショナリに型指定ができる」などの言語仕様により、Objective-Cよりも不具合に気が付きやすくなっています。

モダンな構文による生産性向上

 SwiftはObjective-Cから構文が大きく変わり、シンプルでモダンな書き方ができるようになりました。特に型推論は強力な機能で、多くの場合で型の省略が可能です。

let value1 = 1
let value2 = method()
let value3 = value1
型を省略できるケース
var value: Int
func method(arg1: Int) -> String {
// ...
}
型を省略できないケース

 SwiftとObjective-Cを比べると、他にも「列挙型の改善」「ジェネリクスの追加」など、多くの面で便利になっています。一方で、便利な面が増えただけではなく、ヘッダーファイルが廃止されたり、importが不要になったりと多くの改善があったので、高い生産性を実現できるかと思います。

Swiftへ移行する手順

 移行は、可能なら全てのファイル一気に置き換えるのがベストです。しかし複数人が同時に開発している場合や、機能追加などの予定が決まっている場合など、一気に変更するのは難しいときもあるでしょう。そういった場合のために、今回は少しずつ変更していく手順をお伝えします。

まずは1ファイルだけ移行してみる

 SwiftとObjective-Cはプロジェクト内で共存することが可能です。ファイル単位で移行できるので、まずは1ファイルだけ移行してその後徐々に移行するとスムーズにいきます。

 例として下図のようなシンプルな「MyApp」アプリを移行してみます。

objg_swift_1.jpg

 まずは、「DetailViewController」をSwiftにしてみたいと思います。

 SwiftとObjective-Cで同名のファイルを作成できるので、下図のように「DetailViewController」というファイル名でSwiftのファイルを作成します。

objg_swift_2.jpg

 初めてSwiftファイルを作る場合は「bridging header」を作るかどうか聞かれるので「Yes」を選択しておきます。そうするとプロジェクト内に「{ProjectName}-Bridging-Header.h」という名前のファイルが生成されます。このファイルはSwiftからObjective-Cのファイルを呼ぶためのものです。詳しい使い方は後ほど説明致します。

objg_swift_3.jpg

 下図のようにObjective-Cの「DetailViewController.m」ファイルのソースコードをSwiftへ移植します。

objg_swift_4.jpg

 この際の注意点ですが、Swiftで「setDetailItem」のようなプロパティのセッターを上書きしたい場合はset/get構文を利用します。今回の場合は値の代入後にメソッドを呼ぶだけだったのでsetではなく「didSet」構文を利用しました。

Objective-CからSwiftを呼ぶ

 次に、MasterViewController.mからSwift版のDetailViewControllerを呼びます。その際、「DetailViewController.h」と「DetailViewController.m」は削除してしまいます。

 Swiftのコードを呼びたい場合は下図のように「{アプリ名}-Swift.h」というファイルをインポートします。今回はアプリ名が「MyApp」なので「MyApp-Swift.h」というファイルをimportしています。

objg_swift_5.jpg

Storyboardの修正

 最後にStoryboardを修正します。「DetailViewController.m」を消したことで、「Module」が「None」になっているかと思いますので、そこを「Current」に直します。

objg_swift_6.jpg

 次に、IBOutletのひも付けをすればStoryboardの設定は完了です。

SwiftからObjective-Cを呼ぶ

 なお、SwiftからObjective-Cを呼ぶ方法も紹介しておきます。SwiftからObjective-Cを呼びたい場合は、先ほど作成した「{ProjectName}-Bridging-Header.h」を使います。

 まずは、このファイルの中でSwiftから呼び出したいObjective-Cのファイルをimportします。そうすると、importしたファイルのObjective-CのクラスをあたかもSwiftのクラスのように呼び出せるようになります。

 Objective-Cで書かれたCocoaPodsのライブラリを呼ぶ場合も同様の方法が使えます。

あとは、繰り返し

 これで一つのファイルの移行ができました。以降は同じようにして1ファイルずつSwiftに移行していけば良いかと思います。

移行する際の3つの注意点

 ここからは移行の際に気を付けることを紹介します。移行の途中でObjective-CとSwiftの共存させる場合の注意点です。

Swiftとマクロ

 上記の例ではスムーズに移行できましたが、実際はSwiftでは使えないものもあります。その中で一番大きいものはマクロかと思います。

 Swiftではマクロを定義できません。そのため、もしSwiftでマクロのようなことを実現したい場合は、どこかのクラスにstatic変数を定義する必要があります。

 すでにObjective-Cファイルで定義されたマクロについては、Swiftでも一部だけ使うことができます。文字列やプリミティブ型については呼び出せますが、それ以外のクラスを定義していたり引数があったりすると呼び出すことができません。

#define MACRO1 1 // Swiftから呼び出せる
#define MACRO2(a) 1 // 引数付きマクロはSwiftから呼び出せない
#define MACRO3 MasterViewController // 文字列以外のクラスはSwiftから呼び出せない

Swiftの一部機能がObjective-Cからは呼び出せない

 大きい点としては列挙型と構造体があります。Swiftの列挙型と構造体はObjective-Cに比べて機能が追加されて使いやすくなっています。しかし、その影響のためか、Objective-CからはSwiftの列挙型と構造体を呼び出すことができません。そのため、Objective-Cでも呼ばれることが多いSwiftクラスでは列挙型と構造体を極力控える必要があります。

 また、ジェネリクスやInt、Floatのオプショナル型を引数や返り値に設定しているSwiftのメソッドはObjective-Cからは呼び出すことができません。

 この辺りはいざ呼び出すまでは気が付かないことが多く、気が付いたときには開発が進んでいて変更困難になりがちです。そのため、Objective-Cから呼ばれることが多いSwiftクラスの実装では極力、これらを意識しながら開発をすると良さそうです。

nilの扱いにおけるSwiftとObjective-Cの違い

 SwiftからObjective-Cのメソッドを呼び出す際も注意する必要があります。前述の通り、Objective-CはSwiftと違って変数にnilが入ることがあります。そのため、Objective-Cのメソッドは「一見オプショナル型ではない(nilを含まない)ように見えますが実はnilが入っている」ということがあります。

 実行時にならなければ気が付かないエラーが増えるので、Objective-CとSwiftが混在する箇所は重点的に検証をする必要があります。

Swift化が決定したら、できるだけ素早く移行!

 以上、本稿ではSwiftへの移行について紹介してきました。

 SwiftとObjective-Cの混在時は上記のような問題がありますし、Objective-CとSwiftを両方触ることによって開発者が頭を切り替えるコストも掛かります。そのため、Swift化が決定した場合は、できるだけ素早く移行する計画を立てて短期間で行う方が良いでしょう。

 移行への問題点は、いろいろありますが、Swiftは短くシンプルに書けるので使っていてとても楽しいプログラミング言語です。皆さまも、ぜひSwiftで楽しいiOSアプリ開発を実現してみてはいかがでしょうか。

筆者紹介

杉本裕樹

田町のベンチャーで働くエンジニア。

仕事ではiPhoneアプリの開発やRailsを使ったWebサービス開発を行っている。最近のマイブームはUnityを使った3Dゲーム開発。


Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。