作成中のアプリに Widget を追加するにあたり、ありとあらゆるつまづきポイントに引っかかったためメモ
環境
- Xcode Version 12.3 (12C33)
- iOS 13 以上
行いたいこと
- 出勤・退勤を打刻するアプリの作成
- ウィジェットから出勤・退勤打刻を行えるようにしたい
- その前段階としてまずウィジェットを表示するところから
引っかかった点
- BundleId の設定
- クラス名
- ウィジェットの追加ができない
- Podfile の設定
- iOS 13 でもビルドが通るようにしたい
- 実機でビルドできない
1. BundleId の設定
- 元のアプリの bundle Id は「com.test-inc.MyApp.develop」および「com.test-inc.MyApp」とする
- 「com.test-inc.MyApp.Widget.develop」として生成した
問題点1(Bundle Id が不正)
以下のようなエラーが発生
error: Embedded binary's bundle identifier is not prefixed with the parent app's bundle identifier.
解決法1
bundle Id を com.test-inc.MyApp.develop.Widget
とした
問題点2(Scheme ごとの Bundle Id 設定忘れ)
develop 環境ではビルドが通るが product 環境ではビルドが通らない
解決法2
WidgetExtension
ターゲット > Build Settings
> Packaging > Product Bundle Identifier
から Scheme ごとの Bundle Id を設定
2.クラス名
問題点
ウィジェット名を「Widget」として作成したところ、自動生成された以下のコード部分でエラー
Widget.swift
@main
struct Widget: Widget {
let kind: String = "Widget"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
WidgetEntryView(entry: entry)
}
.configurationDisplayName("My Widget")
.description("This is an example widget.")
}
}
'Widget' is annotated with @main and must provide a main static function of type () -> Void or () throws -> Void.
解決法
Widget
は既に使われているため、構造体の名前を変更
Widget.swift
@main
struct TimeCardWidget: Widget {
let kind: String = "Widget"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
WidgetEntryView(entry: entry)
}
.configurationDisplayName("My Widget")
.description("This is an example widget.")
}
}
3. Podfile の設定
問題点
- シミュレータでビルド後ホーム画面に遷移しウィジェットの追加を試みても対象アプリのウィジェットが表示されない
解決法
- Podfile に以下を追加する
Podfile
target 'WidgetExtension' do
end
4. ウィジェットが Swift UI のUI確認画面に表示されない
問題点1. Scheme の選択
- Scheme として
WidgetExtension
を選択しているとウィジェットのUIのプレビューを表示しようとするとエラーが表示される
解決法1
- Scheme として
MyAppDevelop
を選択
問題点2. Architectures
の設定
ビルド時に以下のようなエラーが発生
(省略) building for iOS Simulator, but linking in object file (省略)
解決法2
- TARGETS から SampleApp と WidgetExtension の Build Settings を変更
-
Architectures > Build Active Architecture Only > Develop
をYes
-
Excluded Architectures > Develop
にAny iOS Simulator SDK
を追加しarm64
に変更
-
- WidgetExtension のみ変更してもビルドエラーが消えなかった
5. iOS 13 でもビルドが通るようにしたい
問題点
Widget 機能自体は iOS 14 以降のものだがアプリの対象は iOS 13以上
解決法
- MyApp の
Development Info
から 対象を iOS 13.0 以上に設定 - WidgetExtension の
Development Info
から対象を iOS 14.0 以上に設定
6. 実機でビルドできない
問題点
- 実機をつなげてビルドしようとすると以下のエラー
"WidgetExtension" requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor.
解決法
- WidgetExtension 用に Provisioning Profile を発行する必要あり
- 今回は開発環境と本番環境で2つ必要
- Widget に利用する Provisioning Profile は App Developer サイトで手動で発行する必要があるらしい
参考
- iOS 14 アプリケーションのWidgetの追加(通常のWidget、Intentsを使用した構成可能なWidget)
- アルを iOS 14 のウィジェットに対応した際いろいろハマったので共有します
- [iOS] Xcode12.0で「building for iOS Simulator, but linking in object file ... for architecture arm64」エラーの対処法
- iOS開発で環境ごとにアイコンやアプリ名、コード等を切り分けるオレオレプラクティス
- iOS Widget provision profile issue: how to correct distribute with iOS WidgetKit