yashiganiの英傑になるまで死ねない日記

週末はマスターバイクでハイラルを走り回ります

CocoaPods0.36をExtensionで使うときに出る警告を抑制する

App Extensionを実装する際,本体のアプリとコードを共有したいことがあります. コード自体をExtensionのターゲットに追加することもできますが,メンテナンス性や複数のアプリで使い回すことを考慮すると,Embedded frameworkとして実装し,各々で取り込むのが理想的です.

しかし,ここで注意する点があります. Extensionでは通常のアプリと違い,いくつかのAPIへのアクセスが禁止されています. 例えば,ExtensionからUIApplicationなどのAPIにアクセスすることができません.

不意にframeworkのコードでこれらのAPIを仕様すると想定の通り動きませんので注意が必要です. そこで,安全にframeworkを共有するためにAllow app extension API onlyというオプションが存在します. (TARGETS > Deployment Info > App Extensionsから指定します.) この設定を有効にすると,framework内のコードで違反をしているときにビルドエラーを発生させることができます. 詳細は以下のドキュメントを参照してください.

CocoaPodsを使うと警告が発生

frameworkに切り出すと独立性が高くなるため,本体のプロジェクトとリポジトリを分けることが可能になります. すると,その取り込みには当然CocoaPodsのようなツールを使いたくなります. 幸いCocoaPodsには0.36よりframeworkのbeta supportが追加されました. podspecを追加し,pod installを実行すると,linking against dylib not safe for use in application extensionsという警告が発生します. この警告は前述した,Allow app extension API onlyオプションが有効でないframeworkをExtensionに取り込んだ場合に見ることができます.

Allow app extension API onlyを有効化したframeworkを取り込んだ場合でもこの警告は発生します. これはCocoaPodsのアーキテクチャに起因する問題です. CocoaPodsはPodを読み込む際,必要なファイルを取り込み,新たにプロジェクトやターゲットを生成して親プロジェクトに埋め込みます. その際,元のプロジェクト設定を引き継いでくれませんので,生成されたframeworkのAllow app extension API onlyはデフォルトでNOになってしまいます. CocoaPodsのframeworkサポートは追加されたばかりなのもあり,この設定をいじるためのAPIは設定は存在しません.

post_installAllow app extension API onlyを有効にする

警告が出たままでは困るのでpost_installで設定を書き換えます. Podfileに以下のようなスクリプトを追加します.

post_install do |installer_representation|
  installer_representation.project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'YES'
    end
  end
end

残念ながらpost_installで変更することは本質的な解決とはいえません. 本来この設定自体はframework側に設定されるものなので,依存する側. しかし,最近出てきたCarthageであればframeworkそのものを利用する設計なので特に困ることがないと思います.. 後発だけあってframework時代に合った仕組みですね. CocoaPodsよりイケテル感があります.

雑談コーナー

config.build_settings['APPLICATION_EXTENSION_API_ONLY']にBooleanを代入していてプロジェクトがぶっこわれました.

参考

追記

laisoさんに対応してるパッチがあることを教えていただきました.

やったね!