Xcode: Embedded Framework でコードをクリーンに管理する
2020-07-12
ハロー、しょーです。
最近めっぽう低気圧に弱くなっております。
昔は雨の日大好きだったんですけどね。
今も雰囲気は嫌いじゃないですが、体調にくるので辛みです。
さて、Embedded Framework でコードをクリーンに管理する という話をしようと思います。
業務では使用してるXcodeの機能ですが、個人アプリでは規模が大きくないこともあり使用してきませんでした。
ですが、最近は設計としてCleanArchitectureを採用することが多く、よりコードをクリーンに保ちたいなと思うことが増えたので勉強がてら導入してみようと思いました!
そのメモになります。
Embedded Framework とは
Embedded Framework とは、Xcode に備わっている機能で、プロジェクトコードの一部を Framework化する機能です。
TARGTS に追加する形で使用します。
フレームワーク化してコードを分割する上で嬉しいことは、
- レイヤーを分けることにより依存関係をより明確に出来る
- ビルド時間の短縮を期待できる
- ターゲットごとにテストを記述できる
という部分がメインのメリットになってきます。
もう少し踏み込むと、
レイヤーを分けることにより依存関係をより明確に出来る
プロジェクトコードの肥大化は管理の困難さに比例します。
そうなった場合、Access Modifiers(アクセス修飾子) などでファイルやコードへのアクセスを制限するのが大事になってきますが、任意の単位でコードを分割することで更にクリーンに管理できます。
(最初は private を設定する意味さえわからなかったけど、最近はアクセス制限の大切さがよくわかってきた)
ビルド時間の短縮を期待できる
Xcodeの差分コンパイルが適応されるターゲットが細かくなるので、ビルド時間の削減につながります。
小規模アプリだと恩恵は少ないかもしれない、、けど他のメリットの恩恵もあるので導入は個人の手腕ですけどね。
ターゲットごとにテストを記述できる
これもフレームワーク、モジュールごとにテストをかけるというのはメリットの一つになります。
API接続などのネットワーク部分だったり、細かく分けられるのはテストの理に適っています。
正直個人アプリは規模が小さいのでテスト全く書いてないですけど!勉強します!
ということで、試しに導入してみよう。
Embedded Frameworkを導入する
今回はCleanArchitecture + Redux の設計をベースに導入していきます。
CLとReduxの併用は、元々レイヤーが細かく切られている設計なのでいい例になるんじゃないかなと思います。
以前レイヤーイメージを作ったので参考としてどうぞ。
Qiita: Redux + Clean Architecture の構造イメージ
いきなり完成図ですが、今回は Entity、state や Reducer などデータ操作のコアを成す部分をフレームワーク化していきたいと思います。
作り途中で Embedded Framework の導入を決めたので、ActionCreator とかいろいろ足りてないのはスルーしてください。
TARGETの追加をする
TARGETS から+ボタンを押して新規ターゲットの追加をします。
テンプレートは Framework と検索すれば出てきます。
あとは名前を決めて作成すればOKです。
ユニットテストを追加するときは Include Unit Tests にチェックを入れてくださいね。
そうすると、.h のヘッダーファイルと .plist ファイルを持ったディレクトリが追加されると思います。
作成までは以上、楽勝。
ファイルの追加とライブラリ設定
ファイルを新規追加する
このフレームワーク内で管理したいものはこの配下に追加していくことになります。
新規ファイルを追加する場合は Targets が該当のフレームワークにチェックして下さい。
既存のファイルを移動する
既存ファイルを移動してくるときはちょっと確認事項が増えます。
自分は途中から導入したのでここで少しハマりました。
新規でフレームワークに追加する場合は、TARGETS > 該当のフレームワーク > Build Phases > Compile Sourcesに新規ファイルが追加されるのですが、
フレームワーク作成後に既存ファイルやディレクトリを移動してきてしまうと自分で追加しないといけないっぽいですね。
後から移動する場合はここに手動で追加しましょう、でないとファイル見つからへんでエラーが出ます。
インスペクターでも操作できますので、エラーが出る人は念のためチェックしてみてください。
ライブラリを追加する
もしフレームワーク内でライブラリを使用したい場合は、このフレームワークに別途追加設定しなくてはなりません。
その場合は、TARGETS > 該当のフレームワーク > Build Phases > Link Binary With Libraries に使用するライブラリを追加してください。
このプロジェクトではSPM (Swift Package Manager) を使用しているので個別で追加してますが、CocoaPods とかの場合は該当フレームワークにもインストールしないといけません。
podfile には初めは以下のように
target YOUR_PROJECT
do
になってると思いますが
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target `YOUR_PROJECT` do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for YOUR_PROJECT
end
個別に使い分けたいときは、別途ターゲットの追加を記述するか、
まとめて使用したい場合は
abstract_target YOUR_PROJECT
do
にするとまとめて設定できるようです(へー知らんかった)。
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
abstract_target `YOUR_PROJECT` do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for YOUR_PROJECT
end
設定するところはこんなものです。
使い方
このフレームワークを外部から参照したい場合は、そのファイルで import FrameworkName するとアクセスできるようになります。
ここで大事になってくるのがアクセス修飾子になります。
引用させてもらいますが、アクセルの許容が大きい順から以下のようになります。
open 別モジュールから呼び出せる。継承やオーバーライドが可能
public 別モジュールから呼び出せるが継承やオーバーライドが不可能
internal 同モジュール内からのみ呼び出せる
fileprivate 同ファイル内からのみ呼び出せる
private 同スコープ内からのみ呼び出せる
private やクラスにつける final くらいは普段使うけど、internal とか使うのって今か!と、無駄におぉ〜となってしまったよ。
通常全体からのアクセスを許可する場合は public を付与しますが、普段は書かなくても省略されて機能しています。(func だけの記述は外部からアクセスできますよね)
ですがフレームワーク内の記述は public はもちろん internal などしっかり記述していこう!
じゃないとわざわざフレームワーク化してレイヤーを分けてクリーンにしている意味もないですからね、アクセス制限をしっかりかけることで機能が最大限に発揮できるんですね、勉強になりました。
public internal(set) など、getだけしたい場合とか活躍してくれるんじゃないでしょうか。
以上です。
まとめ
業務のプロダクトコードはもちろん、大人数が触るのでこのように秩序をもたらすのは大事ですが、個人開発はオレオレになってしまうので手を抜きがちです。
ですが個人開発だからこそ、こんな機能次実装しよう〜とか、自由な新しいアイディアを好きな時に追加できるのが強みなので、このようなクリーンなコードを保つ知識は積み重ねて使用していきたいなと思いました。
ただ小規模アプリにCLや細かいレイヤー整備はオーバーキルなので、この辺は選定が必要ですが、、
でも導入して、部屋を掃除した後の
うん、とても綺麗だ!(ドヤ
と同じ感覚というか、整理整頓したら少し心が晴れたのでよかったです。
よければやってみてください。
お疲れ様!じゃな!
アプリリリースしました!
持ち歌とそのキーを登録できるアプリです!
自分のキーをよく忘れる方は使ってみてください!
関連記事
【Xcode】Xcode13を共存させるとXcode12系でgpxファイルが出現しない不具合の対処法
お疲れ様です。 今回Xcode13対応をしようと思い導入したところ、Xcode1 ...
【Swift】iOS13のCollectionView、CompositionalLayoutsでモダンにレイアウトする
おはようございます!しょーです! 最近は社内ペアプロをよくやっており、問題解決に ...
Swift: map()でゴチャついた処理をreduce(into:)でスッキリ
こんつぁ、しょーです。 イテレーション、繰り返し処理の話をしよう。 reduce ...
【SwiftUI】Stackに詰め込んだTextが省略されるのを解消する
こんにちは。 SwiftUI、ようやっとキャッチアップ始めました。最近はこいつを ...
iOSアプリ開発:初期マストでいれるライブラリまとめ
ワッツァップピーポー、しょーです。 最近また作りたいアプリがどんどん出てきたので ...
ディスカッション
コメント一覧
まだ、コメントがありません