Widget Extension
iOS 14からホーム画面やToday Viewに Widget Extension を設置できるようになりました。
実装は必須ではありませんが、ここでは、最新のお知らせタイトルを表示する方法についてご紹介します。
Extensionの作成
File > New > Target > iOS > Application Extension から、Widget Extension を選択し、Extension を作成します。

App Groupの作成
アプリ本体と Widget Extension でデータを共有するためには、App Group を作成することが必要です。
- ブラウザから iOS Dev Center にログインし、App Groups から App Group を作成します。

- App IDs から iPhone アプリを選択し、App Groups を有効化します。プロビジョニングプロファイルは再作成してください。

- iOS Dev Center において、Widget ExtensionのApp ID を作成します。(Xcode によって自動的に作られている場合もあります。)
- ここからは Xcode 上の作業となります。
iPhone アプリと Widget Extension の TARGETS において、それぞれ Capabilities から App Groups を有効化します。

アプリ側のコーディング
AppDelegate.swift において、お知らせを FANSHIP サーバーから取得した際にコールされる PopinfoReceiver デリゲートメソッドを実装します。
そのタイミングで、Widget Extension とデータを共有できる領域に最新のお知らせを保存します。
func popinfoReceiver(_ popinfoReceiver: PopinfoReceiver, updateMessagesResult result: Bool) {
// 通信に失敗した場合は return
guard result else { return }
// 最新のお知らせを取得する
let myListVC = PopinfoListViewController(nibName: "PopinfoListViewController", bundle: Bundle.main)
let messages = myListVC.retrieveAllPopinfoMessages()
guard messages.count > 0 else { return }
let latestMessage = messages[0]
// Widget Extension と連携するため、共有領域に最新のお知らせのタイトルと日時を保存する
guard let ud = UserDefaults(suiteName: "App Group 名") else { return }
ud.set(latestMessage.piTitle, forKey: "messageTitle")
ud.set(latestMessage.piTime, forKey: "messageTime")
// Widget Extensionのタイムラインを更新する
WidgetCenter.shared.reloadAllTimelines()
}
Widget Extensionのコーディング
Extension を作成した際、Xcode のアプリプロジェクト上で、Product Nameで指定した名前のswiftファイルが自動で生成されます。
アプリ側で保存した値を読み込む例としては、以下のようなstructを用意して、Textなどで表示してください。
struct NewMessage {
static let group = UserDefaults(suiteName: "App Group 名")
static var messageTitle = group?.string(forKey: "messageTitle") ?? "お知らせはありません"
static var messageTime : String {
guard let time = group?.object(forKey: "messageTime") as? Date else { return "" }
// 年月日ラベル用フォーマッタ
let formatter = DateFormatter()
let calendar = Calendar(identifier: .gregorian)
formatter.calendar = calendar
formatter.locale = NSLocale.system
formatter.timeZone = NSTimeZone.system
formatter.dateFormat = "yyyy/MM/dd"
return formatter.string(from: time)
}
}