はじめに
こんにちは。モバイルエンジニアの大澤です。 普段はあすけんのAndroid/iOSアプリを開発しています。今回はiOS18からサードパーティ製アプリに解放されたコントロールウィジェットの対応についてまとめました。
コントロールウィジェットとは
アプリのコントロールをコントロールセンターやロック画面などに追加できます。
ボタンを押すことで定義したアクションを実行できます。
種類として、ボタンとトグルがあります。
developer.apple.com

開発環境
Xcode16 Minimum Deployments iOS16.0
実装
ボタンをタップするとアプリが起動し、食事区分の選択肢が表示され、選ぶとバーコードスキャン画面へ遷移するという機能です。 あすけんではすでにウィジェット機能をリリース済みでしたのでWidgetBundleに追加するだけで 実装は完了しました。 アイコンはSF Symbolsを利用することで最小限で実装できました。

注意点
バージョン分岐
コントロールウィジェットはiOS18以降対応ということで分岐の実装が必要です。
注意点として、WidgetBundleのbodyに追加するときに#available(iOS 18, *)を使うとiOS17以下でウィジェットが使えなくなる問題が発生します。
「iOS 18」の指定だとApp Extensionとマッチしないのが原因でした。
#available(iOSApplicationExtension 18.0, *) を使うことで「iOS18以上のApp Extension」という条件になり正常に動作するようになります
カスタムURLスキーム対応
「コントロールウィジェットを活用し、アクション実行後にその内容に応じた処理をアプリ側で制御できるようにしたい」という要望がありました。
最初にユニバーサルリンクを試しましたが、ウェブページが一度開かれてしまうなど、期待した挙動にはならなかったため、ユニバーサルリンクの使用は断念しました。
調査を進めていく上でカスタムURLスキームが対応可能だということがわかり実装方法を変更しました。
ただし、Workaroundな実装なのでより良い実装があれば修正したいです。
下記の方法で実行できるようにしました。
- メインターゲットにコントロールウィジェットのファイルを追加
- AppIntentのperform()の内部でEnvironmentValues().openURLを実行する
@MainActor
func perform() async throws -> some IntentResult & OpensIntent {
let url = URL(string: "test://test")!
EnvironmentValues().openURL(url)
return .result(opensIntent: OpenURLIntent(url))
}
まとめ
すでにウィジェット対応しているアプリではとても簡単に追加可能なので ぜひ試してみてください!
参考記事
- https://forums.developer.apple.com/forums/thread/759670
- https://stackoverflow.com/questions/75402219/available-iosappextension-vs-ios
- https://stackoverflow.com/questions/78716058/ios-18-control-widget-that-opens-a-url
- https://developer.apple.com/jp/videos/play/wwdc2024/10157/
askenでは新しい仲間を募集しています! www.asken.inc