Embedded frameworkの理解と作成方法
Table of Contents
開発中のビルド時間の短縮やレイヤードアーキテクチャをより疎結合にする設計や、Extensionや他Platformなどでコード共有したい場合は、Embedded frameworkで解決できます。
Embedded Frameworkとは?
事前に組み込まれたフレームワークです。static libraryみたいな扱いです。
例を使って説明
例えばiOSアプリターゲットにA,B,Cというソースコードが含まれてたとします。
このうちCファイルを別のframeworkターゲットとして抜き出して、
それを元のiOSアプリターゲットのフレームワークとして組み込む方法です。
Embedded Frameworkのメリット
一見助長に感じる制御フローですが、次のケースでその恩恵を得られます。
ケース1: 他プラットフォームのコード共有
最近のアプリケーションではiPhone(iOS)に留まらず、watchOSやtvOSなど複数端末で一つのサービスを横断して使うことでサービス体験を向上させてます。
またAPIのバージョンアップによりアプリ外のサービスにも機能拡張できるApp Extensionによりアプリ外にもサービスロジックが必要になるなど、現状のアプリは、複数プラットフォーム展開によるコード流用のニーズが高いです。
watchOS | AppExtension |
---|---|
Embedded frameworkは、iOSアプリターゲットからコードを抽出し別ターゲットで管理することでiOSアプリターゲット以外でもframeworkとして使うことができることで、コード共有を実現しています。
ケース2: ビルド時間の短縮
Xcodeで使われているビルダーではインクリメンタルビルドをサポートしており、開発中では主にこのビルド方式が多く使われます。 このインクリメンタルビルドは変更があった箇所と変更に影響ある箇所だけをビルドすることでビルド時間短縮します。
これをコードをframeworkで分離することでコード改修した箇所でframework先まではビルドされることはないので、より少ない時間でビルドが終わります。
同じ理論でビルド時間短縮してるのがCocoaPodsからのCarthageになります。
ケース3: レイヤードアーキテクチャの疎結合を強化
Embedded frameworkといってもframeworkと同じ扱いになり、framework内の機能を使うにはimport
しないとコンパイルエラーとなります。
つまり言語レベルでレイヤー間のアクセス違反を検知してくれるようになります。
(検知といっても検知した後はエンジニアが気づく必要があるので完璧とはいえないですが)
Embedded Frameworkを作る
仕組みがシンプルですが、実装方法もシンプルです。
- Frameworkターゲット追加
- 作成されたフォルダ内にコード実装
- アプリターゲット > Generalからフレームワークを追加
- アプリ側コードからimportして呼び出し
では実際にLogicというEmbedded frameworkを用意し、中にはCalculatorという構造体を用意してみます。
Frameworkターゲット追加
プロジェクトのGeneralからターゲット追加します。↓
Frameworkを選択します。↓
注意点としてXcodeは定期的にUIを変更するため、時期によってはこの画面や名称とは違うケースがあります。
作成されたフォルダ内にコード実装
Frameworkターゲットを追加するとターゲットと一緒にフォルダも作成されます。
コードは何でもいいですが、今回は下記コードをFrameworkの管理するフォルダに追加します。
public struct Calculator {
public static func plus(vals: Int...) -> Int {
vals.reduce(0, +)
}
}
アクセススコープに注意
framework全般の常識として外部から使われることを想定しているクラスやメソッドのスコープをpublicにして呼び出し元から見えるようにします。
スコープ未指定だとframework外だと見えないので注意です。
アプリターゲット > Generalからフレームワークを追加
作成したframeworkをiOSアプリターゲットから使えるようにするために関連付けする必要があります。
アプリターゲットのGeneralからframework追加を行います。
+
を選ぶことで選択ダイアログが出てきますが、内部ターゲットになるのですぐ見つけれます。
アプリ側コードからimportして呼び出し
あとは使いたい場所でimportして呼び出すだけです。
import UIKit
import logic
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print(Calculator.plus(vals: 0, 1, 2))
}
}
今回のコードはGitHubにあげてあります。実際にXcode立ち上げて確認したい方はどうぞ。