【Xcode】iOS14から利用できる「WidgetKit」の実装(Simple Memo-Ultimate-の実装より)

Xcode(Swift/Objective-C)における、技術メモです。

弊社アプリ「Simple Memo-Ultimate-」に、iOS14から利用できるようになった「WidgetKit」を組み込みました。
相変わらず色々と苦戦しましたが、自身の脳内整理・備忘録を兼ねてメモしています。

※もし内容に誤りなどございましたら、下部「コメント」欄にいただけるとありがたいです。

iOSアプリ

Information iPhone/iPad用のテキストエディタアプリです。 ※「Apple Silicon(M1) Mac」において、iPadアプリとして動作することを確認しております。 iOS14以降で利用可能なウィジェット[…]

関連記事

弊社のiOSアプリ「Simple Memo-Ultimate-」のVer.5.0をリリースいたしました! リリース内容 アップデート内容 <新規機能> ウィジェットに対応しました(iOS14以降必須) iOS14の新機能「[…]

開発環境

  • Xcode Version 12.0.1(12A7300)
  • iOS(iPhone/iPad)向けアプリの開発

「WidgetKit」とは?

iPhoneのホーム画面に「情報を表示できるウィンドウ」を作れる、というものです。

WidgetKitの概念や仕掛けについては、非常によくまとめられておりますページがございますので、ご参照ください。

Qiita

※この記事は2020/7/28時点のBeta3の情報を元に作成しています。 2020/7/25 IntentConf…

今回、必要だった機能

弊社アプリ「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を付与し、その画面に遷移する方法を採用しました。

関連リンク

iOSアプリ

Information iPhone/iPad用のテキストエディタアプリです。 ※「Apple Silicon(M1) Mac」において、iPadアプリとして動作することを確認しております。 iOS14以降で利用可能なウィジェット[…]

関連記事

弊社のiOSアプリ「Simple Memo-Ultimate-」のVer.5.0をリリースいたしました! リリース内容 アップデート内容 <新規機能> ウィジェットに対応しました(iOS14以降必須) iOS14の新機能「[…]

Qiita

※この記事は2020/7/28時点のBeta3の情報を元に作成しています。 2020/7/25 IntentConf…

記事情報や役立ち情報を発信します!
Click to Hide Advanced Floating Content
Click to Hide Advanced Floating Content