- iOS 7時代 (Xcode 5) より前に作成されたプロジェクトである
- Swiftのコードを一行も含んでいない
IOS_DEPLOYMENT_TARGET
が8.0よりも小さい (7.xをサポートしている)
こんな由緒正しいiOSのプロジェクトを未だにメンテしている人もなかなかいないのかと思いますが、もしいらっしゃいましたらそんな方のためにSwiftなプロジェクトに変換していく方法をメモしておきます。
■前提条件
まずIOS_DEPLOYMENT_TARGET
を8.0以上にしましょう。IOS_DEPLOYMENT_TARGET
を8.0以上にすることでdynamic frameworkおよびclang moduleが使えるようになるため、Objective-CとSwiftの間の垣根が非常に低くなります。■ケース1: 根っこはObjective-Cのまま、Swiftのファイルを追加
普通にSwiftのファイルを追加したらXcodeが上手いことしてくれます。具体的にはclang moduleを有効にしてdyldを使えるようにする設定
CLANG_ENABLE_MODULES = YES;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
Swift化されるターゲットごとにブリッジングヘッダを作成
SWIFT_OBJC_BRIDGING_HEADER = "myapp/myapp-Bridging-Header.h";
Releaseビルド以外に対して最適化レベル設定
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
が自動的に行われるので後はせいぜいブリッジングヘッダに使ってるObjective-Cのヘッダを書き込む程度ですみます。
■ケース2: 根っこからSwiftにする
「根っこからSwift」とは要するにmain.m(C言語のmain関数)を持たないアプリにしたいということですが、これも実は思ったより簡単にできます。- AppDelegate.swiftファイルを作成する
- 既存のObjective-Cで書かれたAppDelegateを継承て新しくswiftなAppDelegateを作成して、
@UIApplicationMain
アノテーションを付ける - main.mを消す
たったのこれだけでプロジェクトの根っこがSwiftな状態になります。簡単ですね。
■さらにSwift化をすすめる
とりあえずAppDelegate.swiftを作ることで根っこはSwiftになるのですが、せっかくだからAppDelegateをまるごとSwiftにしてしまいたいものです。ここでもし、- UIWindowをAppDelegate内部でカスタマイズしている
- UIApplicationをmain.mでカスタマイズしている
まずUIApplicationについてはInfo.plistの
NSPrincipalClass
を変更することで任意のカスタムクラスに差し替える事が可能です。参考はこちら: http://stackoverflow.com/questions/31642956/how-to-detect-all-touches-in-swift-2UIWindowについてはMain.storyboardを使わなければ勝手にUIWindowを差し込まれることはなくなるので問題ないのですが、それでは困ると言う場合は
awakeFromNib
とかを実装してその中で@UIApplicationMain class MyAppDelegate: NSObject, UIResponder, UIApplicationDelegate { var window: UIWindow? override func awakeFromNib() { super.awakeFromNib() guard let defaultWindow = self.window else { fatalError("Something is wrong") } let window = MySuperDuperWindow() window.rootViewController = defaultWindow.rootViewController self.window = window } }とかすれば動くと思います。多分。