iOSエンジニアの遠藤です。 先日iQONで、Xcodeのビルドパフォーマンス改善の一環としてEmbedded Frameworkの導入を行いました。 今回は、そのEmbedded Frameworkの導入について紹介したいと思います。
Embedded Frameworkとは?
Embedded FrameworkはiOS 8・Xcode 6から追加された機能です。 アプリのコードを分割してFrameworkとして扱うことができます。
Embedded Frameworkを導入することのメリット
コードを分割してFramework化することで以下のメリットがあります。
- コードのターゲットが分かれるため、差分コンパイルされビルドパフォーマンスが向上する
- App Extentionsを持つアプリの場合、メインターゲットとExtension間でコード共有することができる
- Frameworkに分けることで、依存関係がシンプルになる
- Frameworkごとにテストを書くことができる
導入方法
Xcode 7.3.2 Swift 2.2での導入方法です。
Frameworkの作り方
Embedded Frameworkの導入は簡単で、Xcodeのツールバーから「File」 → 「New」 → 「Target」を選択すると、以下の画面が表示されます。
そこから「Framework & Library」 → 「Cocoa Touch Framework」を選択すると新しくターゲットが追加されます。
新しくできたTargetに分けたいコードを追加していきます。
Frameworkの使い方
Frameworkとして扱うメソッドやclass、変数にはメインターゲットからアクセスできるように public
修飾子をつけてください。
import Foundation import Alamofire public class Util { public var name: String? public init() { } }
使用したいFrameworkをimportするだけで使えるようになります。
import UIKit import SampleFramework class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let util = Util() util.name = "hoge" } }
Embedded Frameworkの導入はすごく簡単です。
しかし、Framework内でライブラリを使う場合はいろいろとハマる部分がありました。 その対応方法をいくつか紹介したいと思います。
CocoaPodsでライブラリを使う場合
Embedded Frameworkだけでしか利用していないライブラリでも、メインターゲットにもインストールする必要があります。
Podfileにターゲットごとに同じライブラリ名を記述するのは手間なので、iQONではabstract_target
でまとめています。
// Podfile abstract_target 'All' do # Targetとかぶらなければ、名前の文字列は何でも大丈夫です pod 'Alamofire' target 'SampleApp' do # AlamofireとSVProgressHUDがインストールされる pod 'SVProgressHUD' end target 'SampleFramework' do # Alamofireがインストールされる end end
Carthageでライブラリを使う場合
CarthageもCocoaPodsと同様にFrameworkとメインターゲットどちらにも、ライブラリを設定する必要があります。
メインターゲットのEmbedded Binaries
にFrameworkで利用しているライブラリを設定します。
Library not loaded
でクラッシュする場合
CocoaPodsでインストールしたライブラリがLibrary not loaded
でクラッシュしてしまう時は「Build Phases」を確認してみてください。
おそらく、インストールしたライブラリをアプリ内に組み込むための Run Script が存在していないためにクラッシュしている可能性があります。
[CP] Embed Pods Frameworks
という名前の Run Script は本来CocoaPodsが自動的に追加するもので、なぜそのRun Scriptが存在しないのかは詳しくは分かりませんが、追加すればクラッシュしなくなります。
Framework not found Pods_**
でビルドが通らない場合
[Build Phases] -> [Link Binary With Libraries]を確認してみてください。 エラーで表示されているFrameworkを削除してください。
以前からCocoaPodsでライブラリを管理しているプロジェクトだと、Pod_**.framework
というものがLink Binary With Libraries
に設定されています。
しかし、Podfileをabstract_target
で書くようにした場合、新しくPods-**-**.framework
というものが設定されるので、Pod_**.framework
が不要になります。
不要なものが設定されているために、ビルドに失敗していました。
導入した結果
まだ、一部分のコードしかFrameworkにできていないので、差分コンパイルによるビルドパフォーマンスの向上はあまり感じることはできていません。
しかし、frameworokに分けることでコードの依存関係が明確化されたのは良かったと思います。 今までコード感の依存関係がごちゃごちゃになっていたのが明確化されたので、コードの設計を見直すきっかけになりました。
まとめ
Embedded Frameworkを導入した話でした。
Frameworkを作ること自体はすごく簡単です。 Framework内でライブラリを使用する際にハマるポイントがいくつかありますが、慣れてしまえばすごく便利でメリットが多いのでおすすめです。
まだiQONは一部しか対応をできていませんが、随時Framework化してビルドパフォーマンスの向上を目指していきたいと思います。
最後に
VASILYでは一緒にiQONを開発してくれる仲間を募集しています。少しでもご興味のある方は以下のリンク先を御覧ください。