Xcode(Swift/Objective-C)における、技術メモです。
弊社アプリ「Simple Memo-Ultimate-」に、iOS14から利用できるようになった「WidgetKit」を組み込みました。
相変わらず色々と苦戦しましたが、自身の脳内整理・備忘録を兼ねてメモしています。
※もし内容に誤りなどございましたら、下部「コメント」欄にいただけるとありがたいです。
究極のシンプルテキストエディタ iPhone, iPad, Apple Watch ダウンロードする (AppStore) 究極のシンプルテキストエディタ iPhone, iPad,[…]
弊社のiOSアプリ「Simple Memo-Ultimate-」のVer.5.0をリリースいたしました! リリース内容 アップデート内容 <新規機能> ウィジェットに対応しました(iOS14以降必須) iOS14の新機能「[…]
開発環境
- Xcode Version 12.0.1(12A7300)
- iOS(iPhone/iPad)向けアプリの開発
「WidgetKit」とは?
iPhoneのホーム画面に「情報を表示できるウィンドウ」を作れる、というものです。
WidgetKitの概念や仕掛けについては、非常によくまとめられておりますページがございますので、ご参照ください。
※この記事は2020/7/28時点のBeta3の情報を元に作成しています。2020/7/25 IntentConfigu…
今回、必要だった機能
弊社アプリ「Simple Memo-Ultimate」において、Widgetを作る上で必要だった機能です。
似たような仕掛けを構築する場合のご参考になれば幸いです。(WidgetKit以外も含みます)
機能概要
- Widgetには、iPhoneで記入済の任意のメモを表示する(ローカルDocumentフォルダにデータあり)
- Widgetをタップすると、そのメモを開いた状態でアプリを起動する
必要となった実装
- WidgetKitの組み込み
- iPhone内のメモデータを使うため、Widgetの設定値は動的に作成する必要がある(Siri Intentを利用)
- iPhone内のデータを参照するためにApp Group(共有コンテナ)を利用する必要がある
- Widgetから任意のアプリページに遷移するためのDeepLink(URL Schemes)設定が必要
「WidgetKit」組み込み方法
WidgetKitを組み込むだけであれば、実は簡単です。
Widget Extensionを追加
File > New > Target > Widget Extension
を追加する。
Product Nameに任意を名前を入力して、Finishしてください。
もちろんWidgetを使うために作成していますので「Activate」しておきましょう。
実はこれだけで、ウィジットとしての動作はします。
エミュレーターを実行してみると、以下のように「ただ時間が表示される」だけのウィジットが生成されています。
(自動生成されているコードがそうなっている)
なお、ウィジットをタップすると、当該アプリが起動します。
Widgetの画面を作成
作成したWidget Extensionにある「xx.swift」ファイルにコーディングしていきます。
Widget画面の設計はSwiftUIで実装していきます。
また、今回はそれぞれのWidgetに対して表示したい「ファイル名」を設定値として保存させておきます。
表示時は「ファイル名」を元に「メモ内容」を取得して表示する必要がありますが、「メモ内容を取得して表示する」といった表示関連の処理も、当Swiftファイルに記載します。
「Widget」の設定(静的)
作成するWidget(のインスタンス)ごとに、設定値を持たせることができます。
「静的」とは、固定で設定値を用意しておくケースです。
今回だと「表示するフォントサイズ」を設定で変更できるようにしました。
静的の場合の実装は比較的簡単です。
上記で作成したWidget Extensionの中にある「xx.intentdefinition」に設定していきます。
ココに設定することで、「xx.swift」にて設定した値を読み取ることができます。
設定方法の詳細は割愛いたしますが、下記の例だと、「Widget」の設定項目が3つある形ですね。(Parameters)
「Widget」の設定(動的)
動的に設定値を変更したい場合は、少し面倒です。
今回だと、ファイルを選択するために「その時点でのiPhoneのメモファイル」の一覧を作成する必要があります。
iPhoneに保存されている状態でリストを変える必要がありますので、都度、今の状況を元にリストを作成する必要があるというわけです。(=動的)
「Intent Definition」を「追加」して、そちらで処理を実装。
結果を上記の「Widget Extension」に渡す、というイメージになります。
「Intent Definition」ファイルの作成
名称がイマイチなのですが、「SiriKit Intent Definition File」を追加します。
(Siriショートカットで使われはじめた機能、だからだと思いますが、今となってはイマイチですよね・・・)
File > New > File
「SiriKit Intent Definition File」
Targetsはアプリ本体をターゲットにして作成。
動的処理の作成
「intentHandler.swift」が生成されますので、そちらに処理を記述します。
今回だと「iPhoneに保存されているメモファイルのリストを作成する」という処理を実装します。(動的部分の処理)
この処理結果が、Widgetの設定項目の設定値として表示されることになります。
Widget Extensionからデータを参照するために
Widgetに限ったお話ではありませんが、Widget ExtensionからはiPhone内部のデータ(Documents配下)を参照することはできません。(iOSのセキュリティ設計上、そのようになっています。)
そのため、iOS8から導入された「App Groups」を使い、共有コンテナ上でやりとりする必要があります。
「App Groups」は、同じ自社製アプリ(=同じApp Groups)であればアプリ間でデータを共有できる、という仕組みです。
アプリ本体とWidget Extensionの両方に、同じ「App Groups」を設定
「App Groups」に関する詳細な設定方法は割愛いたしますが、アプリの「Siging & Capabilities」に「App Groups」を追加する形になります。
TARGETS:「アプリ本体」「Widget Extension」「Intent Extension」等、共有コンテナを利用するTARGET全てに「App Groups」を追加してください。
※なお、当然ですが、iPhoneの「Document」と「共有コンテナ」は別の(ローカル)場所です。
「Document」にあるデータは「共有コンテナ」にコピー or 移動が必要となります。
DeepLink(URL Schemes)を有効化
WIdgetをタップした時に遷移する画面を変更するために、アプリ自体が外部から任意の画面を開けるようにします。
これを「DeepLink(URL Schemes)」と言います。
有効化
こちらも詳細な設定方法は割愛いたしますが、アプリの「Info」>「URL Types」から設定が可能です。
「URL Schemes」に設定した値で、外部からアクセスできるようになります。
例えば、「abc」とセットすると、「abc://」で当アプリが起動できるようになります。
なお、iPhone内でユニークであれば問題ないのですが、他アプリとこの値が重複するケースがあり得ます。
その場合、どちらのアプリを開くかは分からないようですので、できるだけ重複しないような値にされることをオススメします。
受けるアプリ側で、URLからハンドリング
「AppDelegate.swift」で外部からのURL送信を受信できますので、どのページに遷移するか、といった処理を実装します。
遷移先の指定は実装方法によりますが、今回はStoryboardIDを付与し、その画面に遷移する方法を採用しました。
絶賛配信中!
メルマガ詳細はこちら >>>
広告を含むご案内のメールをお送りする場合があります。
以下も、ぜひご活用ください^^