◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SONNET 4.5 — Claude API での提供終了は 11/30、残り27日。API 連携を足したアプリは移行先の確認を●SDK 58 — React Native 0.88 に更新されました。Android のリリース版で R8 が既定オンになり、iOS は SceneDelegate を生成します●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SONNET 4.5 — Claude API での提供終了は 11/30、残り27日。API 連携を足したアプリは移行先の確認を●SDK 58 — React Native 0.88 に更新されました。Android のリリース版で R8 が既定オンになり、iOS は SceneDelegate を生成します●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/開発ツール
⬡ 開発ツール/2026-06-18上級

Rork Max の通知を長押しすると自前の画面が出る — Notification Content Extension の実装

Rork Max が生成した Swift アプリに Notification Content Extension を足し、通知を展開したときだけ自前の UI を描く実装をまとめました。Service Extension との役割分担、ボタンで通知内 UI を更新する手順、App Group での状態共有、出ないときの確認順を実コードで整理します。

Rork Max235Notification Content Extensionプッシュ通知20UserNotificationsSwift48App Group4

✦ プレミアム記事

毎朝ひとつだけ作品を届ける、小さな個人開発アプリを App Store で運用しています。プッシュ通知に画像は出せるようになったのですが、ある日ユーザーから「通知から直接その日の絵を保存したい」という要望が届きました。通知をタップして本体を開かせるのではなく、通知の中で完結させたい。これは標準のリッチ通知では届かない領域でした。

通知の見た目を変える仕組みには二つあり、最初に私自身がここを混同していたので、まずその切り分けから始めます。Rork Max はネイティブ Swift を生成してくれますが、「通知の中に自前の画面を描く」という部分は、生成された雛形をそのまま動かすだけでは出てきません。Extension のターゲット追加、カテゴリの一致、メモリの制約といった泥臭い箇所を、自分のアプリに組み込んだ順番で書いていきます。

Service Extension と Content Extension は役割が違う

UserNotifications には拡張ポイントが二つあります。混同すると「画像は出るのにボタンが効かない」「UI を作ったのに表示されない」という迷路にはまります。

拡張動くタイミングできることできないこと
Notification Service Extension通知が届いた直後・表示される前ペイロードの書き換え、画像など添付の取得、復号UI を描くこと・ユーザー操作に反応すること
Notification Content Extensionユーザーが通知を展開したとき自前の ViewController で UI を描く、ボタンで UI を更新する届く前のペイロード加工(それは Service 側の仕事)

整理すると、画像をダウンロードして通知に添付するところまでは Service Extension の担当、その通知を長押し(または下スワイプ)で展開したときに「保存」ボタン付きの自前カードを描くのが Content Extension の担当です。今回の要望は後者でした。二つは併用でき、実際の本番ではセットで使うことが多いと感じています。

カテゴリという「合言葉」で結びつける

Content Extension が表示されるかどうかは、すべてカテゴリ識別子の一致で決まります。流れはこうです。

  1. 本体アプリで UNNotificationCategory を登録する(識別子と、付けたいアクションボタン)
  2. プッシュのペイロードに同じ識別子を category として載せる
  3. Content Extension の Info.plist の UNNotificationExtensionCategory に同じ識別子を書く

この三つが一文字でもずれると、カスタム UI は黙って出ません。エラーも出ないので、最初の失敗はたいていここです。

本体アプリ側の登録は、起動時に一度だけ行います。

import UserNotifications
 
enum NotificationSetup {
    static func registerCategories() {
        let save = UNNotificationAction(
            identifier: "SAVE_PICK",
            title: "保存",
            options: []
        )
        let openShuffle = UNNotificationAction(
            identifier: "SHUFFLE_PICK",
            title: "別の作品を見る",
            options: []
        )
        let dailyPick = UNNotificationCategory(
            identifier: "DAILY_PICK",          // ← この合言葉が要
            actions: [save, openShuffle],
            intentIdentifiers: [],
            options: []
        )
        UNUserNotificationCenter.current()
            .setNotificationCategories([dailyPick])
    }
}

送信するペイロード側は、同じ category を持たせ、Service Extension に画像を取りに行かせるため mutable-content も立てておきます。

{
  "aps": {
    "alert": { "title": "今日の一枚", "body": "本日の作品が届きました" },
    "mutable-content": 1,
    "category": "DAILY_PICK"
  },
  "image_url": "https://example.com/picks/2026-06-18.jpg"
}
✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦Service Extension(届く前に書き換える)と Content Extension(展開時に描く)の役割を切り分け、自分のアプリでどちらが必要かを判断できます
✦UNNotificationExtensionCategory・UserInteractionEnabled など Info.plist の4キーと、ボタン押下で completion(.doNotDismiss) を返して通知内 UI を更新する実コードが手に入ります
✦App Group 経由で「保存」状態を本体アプリと共有する設計と、カスタム UI が出ない6つの原因を確認する順番がわかります
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

⬡ 開発ツール2026-05-01
Rork アプリに Notification Service Extension を後付けする — 画像付き通知・暗号化ペイロード復号・動的書き換えの実装メモ
Rork で作った iOS アプリに Notification Service Extension を後付けし、画像付き通知・E2E暗号化ペイロードの復号・APNs ペイロードの動的書き換えを本番品質で動かすまでの設計と、実際に踏んだ落とし穴を、動作する Swift コードとともにまとめました。
⬡ 開発ツール2026-04-05
Rork Max × WidgetKit・ライブアクティビティ実装ガイド 2026 — Dynamic Island 対応まで
Rork Max で iOS Widget・ロック画面ウィジェット・Dynamic Island 対応のライブアクティビティを実装した記録。Timeline の焼き込み設計、APNs のヘッダーと優先度、push-to-start、stale-date の扱いまで実運用の判断を残します。
⬡ 開発ツール2026-07-18
文字サイズ最大とドイツ語で、生成された画面は静かに詰まる — Rork Max の SwiftUI にレイアウト耐性の検証を通した記録
Rork Max が生成した SwiftUI 画面を疑似ローカライズと最大文字サイズに通し、どこから詰まるかを機械的に洗い出した記録です。ViewThatFits・ScaledMetric・layoutPriority の使いどころと、再生成のたびに回帰を捕まえるスナップショット検証を、実際の数値とともにまとめました。