OpenAIExpoJun 18, 2026, 2:15 PM

iOS widgets and Live Activities are stable in Expo SDK 56

A condensed section focused on the key takeaways first.

Original Post

Quick Digest

Summary

A condensed section focused on the key takeaways first.

openaienmodel: gpt-5-mini-2025-08-07

iOS widgets and Live Activities are stable in Expo SDK 56

Key Points

  • expo-widgets is stable in SDK 56
  • Widgets receive full WidgetEnvironment and no pre-rendering
  • Configurable widgets and improved error handling

Summary

Expo SDK 56 promotes expo-widgets to stable. You can build iOS Widgets and Live Activities as React components using Expo UI while Continuous Native Generation handles the Widget Extension target, App Group configuration, and SwiftUI scaffolding — so there’s no separate Xcode project to maintain. The SDK 55 alpha has been hardened and now adds practical improvements like full environment delivery, no pre-rendering, configurable widgets, and better error handling.

Key Points

  • Stable expo-widgets: write widgets and Live Activities in React; the system renders them natively via SwiftUI.
  • Continuous Native Generation creates and keeps the widget extension and app group configuration in sync — no separate iOS target to maintain.
  • Widgets and Live Activities now receive full context through WidgetEnvironment (family, content margins, color scheme, rendering mode, presentation and accessibility context).
  • Widgets no longer require pre-rendering by the main app; the widget bundle can render independently in its sandboxed JS runtime.
  • SDK 56 adds configurable widgets so users can pick options from the widget gallery.
  • Live Activities use the same React model but expose multiple slots (Lock Screen, Dynamic Island compact/expanded/minimal) and accept updates via APNs or app-triggered updates.
  • Small implementation notes: use the 'widget' directive for the render function, createWidget(...) to register, and Expo UI components that map to SwiftUI primitives.

Practical guidance for engineers

  • Install and prebuild: expo install expo-widgets then run expo prebuild.
  • Start small: ship one widget that has a single clear job (e.g., ETA, counter, next meeting) before adding Live Activities.
  • Use a widget to learn the rendering model; add a Live Activity when the flow has a clear start, active updates, and an end (and when server-side update/APNs handling is required).
  • Test on device for Dynamic Island / Lock Screen behavior and validate update flows (local vs APNs).
  • Report production feedback and engagement data on Discord or GitHub to help prioritize follow-ups.

Full Translation

Translations

A translation section that keeps the flow of the original article.

openaijamodel: gpt-5-mini-2025-08-07

iOS ウィジェットと Live Activities が Expo SDK 56 で安定化

Widgets と Live Activities は、ユーザーがわざわざアプリを開くよりも手間がかかる場面を減らすために最適です。配達の到着予想、ワークアウトタイマー、フライトステータス、次のミーティング、保存したショートカット――こうした情報はユーザーが別の作業をしている最中に欲しいものです。ウィジェットと Live Activities は、ユーザーにアプリを開くことを要求せずにアプリを有用に保ちます。

React Native アプリからこれらのサーフェスを構築するには従来、別の Xcode ターゲット、App Groups、SwiftUI のレイアウトコード、そしてその拡張をアプリ本体と同期し続ける負担が伴っていました。SDK 56 からは、expo-widgets が安定版になりました。Expo UI を使って React コンポーネントとしてウィジェットと Live Activities を構築できます。Continuous Native Generation が Widget Extension ターゲット、App Group の設定、SwiftUI のスキャフォールディングを処理するので、別個の iOS プロジェクトを維持する必要はありません。

これは SDK 55 でアルファ版として出荷した同じライブラリで、耐久性を高めて安定化したものです。コアの考え方は変わっていません:ウィジェットを React で書き、システムに SwiftUI 経由でネイティブにレンダリングさせ、更新は Expo アプリから管理します。SDK 56 で変わったのは、安定化の保証と実用的な改善点のセットです:ウィジェットと Live Activities は環境情報を直接受け取るようになり、メインアプリで事前レンダリングする必要がなくなり、エラー処理も改善されました。

なぜウィジェットと Live Activities を作る価値があるのか

目的は UI の完全性ではなく、サーフェスの拡張です。アプリアイコンはアプリへの一回のタップです。ウィジェットはゼロタップで、ユーザーが別の作業をしている間にも価値を提供できます。Live Activity は進行中のイベント中に常に表示され、状況が変わるたびに更新され、デバイスがロックされていても有効です。これらのサーフェスは、フルセッションが不要な時に関連情報を近くに保つことでアプリを補完します。

Flighty は良い公開事例です。Interaction 部門で 2023 Apple Design Award を受賞し、Apple の解説でもここで重要な点が挙げられています:Live Activities、Dynamic Island 連携、ウィジェット対応、および旅行者にとって必要な主要なフライト情報を適切な場所に配置している点です。フライトトラッカーにとって、これはプロダクト体験そのものです。旅行者はゲート変更、搭乗状況、到着時間を繰り返しアプリを開かずに知りたいと考えています。Flighty はそれらの情報をロック画面と Dynamic Island に置き、実際に旅が進行しているときに利用できるようにしています。

実運用で勝つパターン:

  • ウィジェット:ユーザーが手元に置いておきたい情報(カレンダー、天気、習慣の連続記録、残高など)
  • Live Activities:開始と終了が明確な「進行中」のイベント(配達の ETA、ワークアウトタイマー、ライドシェア、進行中のフライトなど)

どちらもユーザーがアプリ内に積極的にいる時間外で、アプリの関連性を保つことができます。

OneSignal の 2024 State of Customer Engagement Report(やや古いがデータは具体的)によれば、iOS Live Activities を利用しているアプリは平均 30 日保持率が 23.7% 高いと報告されています。Live Activity を追加すれば自動的に保持率が上がるという保証ではありませんが、同じプロダクトパターンを示唆しています:適切な場所で適時に情報を表示することは、アプリに戻ってくるハードルを下げ得ます。

SDK 56 で何が安定したか

アルファは SDK 55(3月)で公開されていました。それ以降、コミュニティでのテストと内部の反復によって、安定版と呼ぶ前に解消すべき粗さが明らかになりました。主な変更点:

  • Widgets と Live Activities は WidgetEnvironment を通じて完全な環境を受け取るようになりました。これには widget family、content margins、color scheme、rendering mode、presentation や accessibility のコンテキストなどが含まれ、ウィジェットがどのようにどこに表示されるかに応じて適応できます。
  • ウィジェットと Live Activities はもはやアプリ側で事前レンダリングする必要がありません。アプリの React ツリーを起動時に走査してウィジェットレイアウトを準備する代わりに、ウィジェットバンドルは現在のサーフェスに必要なコンテキストで独立してレンダリングできます。
  • 設定可能なウィジェット(configurable widgets)をサポートし、ウィジェットギャラリー上でユーザーがウィジェットの表示内容を選べるようになりました。従来のようにすべての選択をアプリ側で行う必要はありません。

最初のウィジェットを作る

ライブラリをインストールして prebuild を実行した後、最小のウィジェットは次のようになります(そのままのコード):

import { Button, Text, VStack } from '@expo/ui/swift-ui';
import { font, foregroundStyle } from '@expo/ui/swift-ui/modifiers';
import { createWidget, type WidgetEnvironment } from 'expo-widgets';
type Props = { count: number };
const CoffeeCounter = (props: Props, environment: WidgetEnvironment) => {
  'widget';
  return (
    <VStack spacing={8}>
      <Text modifiers={[font({ size: 48 })]}></Text>
      <Text modifiers={[font({ size: 32, weight: 'bold' })]}>
        {props.count}
      </Text>
      <Button modifiers={[foregroundStyle('white')]} label="+" target="increment" onPress={() => ({ count: props.count + 1 })} />
    </VStack>
  );
};
export default createWidget('CoffeeCounter', CoffeeCounter);

関数本体をウィジェットレンダーコンテキストとしてマークするのが "widget" ディレクティブです。これはメインアプリとは別のサンドボックス化された JS ランタイムで実行されます。Expo UI のコンポーネントは SwiftUI のプリミティブに直接マッピングされるので、システムはウィジェットをネイティブにレンダリングしつつ、ウィジェットのロジックは TypeScript 側に残ります。

Live Activities でも同様のモデルが適用されますが、複数のスロット(ロック画面バナー、Dynamic Island の compact/expanded/minimal など)を記述し、システムがコンテキストに応じて適切なスロットを選びます。更新はサーバー経由の APNs でプッシュするか、アプリから直接トリガーできます。

ウィジェット vs Live Activity:どう決めるか

概要は前述で十分ですが、実装上のトレードオフは異なります。まず共有したい情報を定義してください。

  • ウィジェットの場合:アプリ外に恒久的に置くに値する情報は何か、どの頻度で更新する必要があるか、どのウィジェットサイズが有用か、タップ時に何が起きるべきかを決めます。ベストなウィジェットは通常、ひとつの明確な役割を持ちます。
  • Live Activity の場合:ライフサイクルを最初に定義します。何がアクティビティを開始するのか?アクティビティ中に何が変化し得るのか?終了時にどの最終状態を表示すべきか?更新はアプリ側から来るのか、サーバーから来るのか、あるいは両方か?

Live Activities はプッシュトークン、サーバーサイドの更新ロジック、状態遷移、解散ハンドリングを含むため、これらの質問は重要です。両方を検討しているなら、ウィジェットから始めるのが現実的なことが多いです。可動部分が少なく、レンダリングモデルに慣れる実用的な手段になります。そのワークフローに慣れたら、開始・更新・終了が明確な製品部分に対して Live Activity を追加してください。

expo-widgets を始めるには

  • expo-widgets をインストールし、widgets reference に従って最初のウィジェットをスキャフォールドしてください。
  • ユーザーがアプリ外で見て恩恵を受ける一つの情報を選び、そのウィジェットを最初に出荷しましょう。
  • アプリに自然な進行中の瞬間があるなら、そのフローのために Live Activity をプロトタイプしてください。

もし実運用での導入や保持・エンゲージメントに関するデータ共有、または次に何を出すべきかのアイデアがあれば、Discord や GitHub で教えてください。実際の数値は、今後の優先順位を決めるうえで特に重要です。