Swift移行時に引っかかりそうなことを解決する!

第3回XcodeプロジェクトのSwiftへの移行とObjective-Cコードの参照

はじめに

前回はSwift言語について解説しました。今回からは、実際にiOSアプリを開発していくために必要なことについて解説して行きます。

第3回の今回は、既存のObjective-CのプロジェクトをSwiftに移行したり、Objective-Cのライブラリを活用する方法を解説します。また、CocoaPodsをSwiftで活用する方法もご紹介します。

新しくSwiftのプロジェクトを作成する場合

新しくプロジェクト作る場合は、Product Nameなどを入力するダイアログの「Language」「Swift」にします。それ以外はObjective-Cの場合と同じです。

図1 ⁠Language」「Swift」にする
図1 「Language」を「Swift」にする

ファイル構成を見て見ましょう。

図2 ファイル構成
図2 ファイル構成

おなじみのAppDelegateやViewControllerがありますが、拡張子が「.swift」になっています。これがSwiftを記述するファイルです。あと、ヘッダファイル(.h)はありません。なにげにこれがすごく嬉しかったりします。

あとはObjective-Cの場合と同じで、ビルド(Run)すればiOSシミュレータが起動して、アプリが表示されます。

既存のObjective-CプロジェクトをSwiftに移行させる場合

すでにObjective-Cで開発を進めている方は、途中からSwiftに切り替えたいケースもあるかと思います。この場合、すべてのコードをSwiftに書き換える必要はなく、既存のObjective-Cコードを残したまま、Swiftのコードを追加していくことが可能です。

その手順を実際の例で見ていきましょう(下記の例では、XcodeでiOSのSingle View ApplicationのプロジェクトをObjective-Cで新規作成したところから始めています⁠⁠。

プロジェクトを開いた状態で、メニューの[File][New][File...]を選びます。表示されるダイアログの左側メニューで[iOS][Source⁠⁠ を選んで、⁠Cocoa Touch Class」を選択します(⁠⁠Swift File」は選びません⁠⁠。

図3 ⁠Cocoa Touch Class」を選択
図3 「Cocoa Touch Class」を選択

次に表示されるダイアログで、クラス名と親クラスを指定します。ここでは、図のようにクラス名を「NewViewController⁠⁠、親クラス(Subclass of:)「UIViewController」としました。言語は「Swift」を選択します。

図4 クラス名を「NewViewController⁠⁠、親クラスを「UIViewController」とした
図4 クラス名を「NewViewController」、親クラスを「UIViewController」とした

ファイルを保存すると、下記のダイアログが表示されます。

図5 ダイアログが表示される
図5 ダイアログが表示される

「Would you like to configure an Objective-C bridging header?」というダイアログですが、⁠Yes」を選択します。すると2つのファイルが追加されました。

図6 2つのファイルが追加された
図6 2つのファイルが追加された

1つは先ほど追加したSwiftファイル、もう1つは「ExampleObjC-Bridging-Header.h」という名前のファイルで、これが「Objective-C bridging header」です。

SwiftからObjective-Cのクラスにアクセスするためには、アクセスしたいObjective-CのヘッダファイルをこのObjective-C bridging headerでインポートする必要があります。その準備をXcodeが行ってくれたのです。

では例として、NewViewControllerからViewControllerクラスにアクセスできるようにしてみましょう。

NewViewController.swiftを開きます。すると、下記のようなクラスの宣言が見つかると思います。

// NewViewController.swift 
class NewViewController: UIViewController {
    ……

これは、UIViewControllerを継承した、NewViewControllerというクラスの宣言です。ではこの親クラス(UIViewController)を、ViewControllerに変更して、ビルドしてみます。

図7 親クラスをViewControllerに変更してビルド
図7 親クラスをViewControllerに変更してビルド

ViewControllerが定義されていないというエラーになります。SwiftからObjective-Cで記述されているクラスが参照できていないためです。

ExampleObjC-Bridging-Header.hでViewController.hをインポートして、参照できるようにします。下記の1行を追加しましょう。

#import "ViewController.h"

これでSwiftからアクセスできるようになり、ビルドが通るようになります。

ちなみに、このクラスが実際に呼び出されるようにするためには、Main.storyboard内のViewに紐づいているView ControllerのCustom ClassをViewControllerからNewViewControllerに変更する必要があります(下図参照⁠⁠。

図8 ViewControllerからNewViewControllerに変更する必要がある
図8 ViewControllerからNewViewControllerに変更する必要がある

この例のように、Objective-Cで書かれた既存のクラスをSwiftで書かれたクラスで継承して、開発を継続していくことができます。もちろん継承するだけではなく、ライブラリを呼び出したりすることも可能です。

CocoaPodsを使ってObjective-Cのライブラリを利用する

iOSアプリ開発においては、CocoaPodsを使ってライブラリの管理をされいている方も多いと思います。Swiftで書かれたライブラリはまだ少ないですが、Objective-Cで書かれた豊富なライブラリをSwiftから利用できます。広く使われているAFNetworkingを例に、使い方を説明します。事前にCocoaPods自体はこちらを参照してインストールしてください。

CocoaPodsの操作はコマンドラインで行います。まずターミナルを起動して、プロジェクトファイルがあるディレクトリにてCocoaPodsの初期化を行います。

$ pod init

そのディレクトリにPodfileという名前のファイルが生成されるので、下記のように編集します。

target 'ExampleObjC' do

pod 'AFNetworking', '~> 2.5'
  
end

ターミナルで、下記を実行します。

$ pod install

AFNetworking のインストールが成功したら、生成された.xcworkspaceファイルを開きます。すると、Podsというプロジェクトが追加されいていて、その中に、AFNetworking.hがインストールされているのが確認できます。

図9 AFNetworking.hがインストールされているのが確認できる
図9 AFNetworking.hがインストールされているのが確認できる

ここまではObjective-Cの場合と変わりませんが、Swiftの場合には、先ほど説明したObjective-C bridging headerでヘッダファイルを読み込む必要があります。AFNetworkingの場合は下記のように記述します。

// in ExampleObjC-Bridging-Header.h
#import <AFNetworking/AFNetworking.h>

これで、SwiftからAFNetworkingにアクセスできるようになりました。試しに、OpenWeatherMapという天気情報サービスのAPIを呼び出してみます。

    // in NewViewController.swift
    override func viewDidLoad() {
        super.viewDidLoad()

        let manager = AFHTTPRequestOperationManager()
        manager.GET(
            "http://api.openweathermap.org/data/2.5/weather?q=tokyo,jp",
            parameters: nil,
            success: { (operation, response) -> Void in
                println("\(response)")
            },
            failure: { (oparation, error) -> Void in
                println("\(error)")
            }
        )
    }

実行すると、Xcodeのコンソールに東京の天気情報が出力されると思います。上記で行っている、インスタンスやメソッドの呼び出し、コンソールへのデバッグ出力方法などについては、次回詳しく説明します。

新規SwiftプロジェクトからObjective-Cを呼び出す場合

Objective-CベースのプロジェクトにSwiftファイルを追加した場合には、Xcodeが自動的にObjective-C Bridging Headerを追加してくれましたが、Swiftベースのプロジェクトの場合には、自分で Bridging Headerを追加、設定する必要があります。

まず、ヘッダファイルをプロジェクトに追加します(下記の例では「BridgingHeader.h⁠⁠。このファイルパス(プロジェクト相対パス)を、下記のようにターゲットのBuild SettingのObjective-C Bridging Headerという項目に設定します。

図10 ファイルパスをターゲットのBuild SettingのObjective-C Bridging Header項目に設定
図10 ファイルパスをターゲットのBuild SettingのObjective-C Bridging Header項目に設定

これで、SwiftからObjective-Cを参照できるようになります。逆に、参照できなくなった場合には、上記の設定を確認すると良いでしょう。

次回は……

今回は、SwiftからObjective-Cを利用する方法を解説しました。現状ではObjective-Cのライブラリを利用する機会もまだまだあると思うので、Objective-C Bridging Headerを使用するケースも多いと思います。

ちなみに、先ほど例で取り上げたAFNetworingですが、いろいろ調べている中で、同じ作者がSwiftベースのAlamofireと言うライブラリを開発していることを知りました。説明に「Elegant HTTP Networking in Swift」とあるので、Swiftを活かしたライブラリになっているのではないかと思います。このように、今後はライブラリのSwift化も進んでいくと思われます。

ここまでで、iOSアプリをSwiftで開発する準備は整いました。次回は、クラスの定義、インスタンス、メソッドの呼び出し、クロージャ、シングルトン、キー値監視、デバッグ方法などを、実際のアプリ開発を例に解説したいと思います。

おすすめ記事

記事・ニュース一覧