ObjCのXcodeプロジェクトをSwiftのプロジェクトに変更する

Objective-Cで作成されているプロジェクトをSwift混在プロジェクトに作り替えようという話があった。
XcodeのテンプレートプロジェクトではObjective-CとSwiftどちらの言語を選べるけど、言語が変わる以上に何が変わるのかというかどこが言語選択のキモになるかを調べたので需要は無いだろうけど、Objective-CベースのプロジェクトをSwiftベースのプロジェクトに作り替えた作業のログを書く。
日本語がおかしかったので編集したらもっと日本語がおかしくなった。

なんでSwift混在にしたいのか

最近は主にSwiftで開発を行っていて、サードパーティーのライブラリもSwiftのものを利用しているから。
Objective-C製のライブラリをSwiftで使うときは割とどうとでもなるけど、Swift製のライブラリをObjective-Cで使うときはライブラリが内部クラスなのか public なクラスなのか設定が必要とかそういうのがあったはず。
そのため新規開発する部分はSwiftで、外部ライブラリを使用したいObjective-Cの実装もSwiftでextensionで実装して、改修が不要だったりシンプルな既存の改修で済むような場合はObjective-Cのままでいこう。みたいな方向で落ち着きました。

ObjCベースのプロジェクトをSwiftベースに移行する流れ

Step.1 Objective-Cのプロジェクトを作成する

Single View Appで作成する。
名前はなんでもいいので ObjcBaseProj にした。

Step.2 Swiftファイル AppDelegate.swift を作成する

AppDelegate.swift を作成する。
Objective-CのプロジェクトでSwiftファイルを作成するのでBridging-Header自動作成の確認されるので作成する。

AppDelegate.swift の中身はSwift用プロジェクトのデフォルトの内容を移植する。

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    // MARK: UISceneSession Lifecycle

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }
}

Step.3 不要なファイルを削除する

  • AppDelegate.h
  • AppDelegate.m
  • main.m

AppDelegate クラスの宣言が重複するためObjective-CのAppDelegateを削除。
main.m も削除する。main.mの内容は AppDelegate.swift@UIApplicationMain が同じ仕事をしているとのことです。また main.m を使って @UIApplicationMain を使わないという方法もあるらしいですが未確認です。 参考URL1

Step.4 ビルド

これで問題無くビルドできるはず。

Step.5 既存Objective-CクラスをBridging-Headerでimportする

このように。
StoryboardやXibファイルではObjective-CのクラスもSwiftのクラスも関係無く呼び出せるので、SwiftファイルでObjective-Cクラスを呼び出さないのであればimportしなくても問題無い。

//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//

#import "ViewController.h"

参考URL

  1. http://tasuwo.github.io/blog/2015/05/30/ios-02/