Why is an app extension a separate process, and what does that mean for how you build it?

6.8.3 · L3 · Interview

Predict first

How do an app and its widget share a decoding function?

// A: through a shared singleton instance
// B: by both linking the same framework or package
// C: by the widget calling into the app’s process
  • A
  • B
  • C

Mental model. An extension is a branch office with its own small safe and tight deadlines. It runs the same company software, but it cannot reach into the head office’s filing cabinets.

An extension (share sheet, widget, notification service, keyboard, Siri intent and many more) is a separate executable inside your app’s bundle, launched by the system when its host asks for it. It is a different process with its own sandbox container, its own memory, and its own lifetime: it starts when the user opens it (or the system needs it) and ends when it is dismissed or when the system reclaims it. It does not share your app’s memory, singletons, in-memory caches or running tasks, and it never runs UIApplicationMain of your app.

That drives the design. Put shared logic in a framework or Swift package that both targets link (so the code, not the objects, is shared). Share data through an app group, a shared keychain group or a shared database. Respect the extension’s much lower memory limit and short time budget: a widget or a notification service extension that decodes large images is killed (see jetsam), so keep work minimal and precomputed by the app. Expect to be launched cold every time, and avoid APIs that are unavailable in extensions (many UIApplication features).

Code is shared by linking it into both executables. Each process then has its own copies of any objects.

AppExtension
Processits owna separate one, per extension
Sandbox containerown data containerown container; shares only through groups
Memory limitmuch largermuch smaller
Lifetimeuser and system drivenuntil dismissed or reclaimed
Shares with the app–code via a framework; data via an app group or keychain group

Common traps

  • Reading a singleton from the extension and expecting the app’s state. Your extension gets a fresh copy, because it is another process.
  • Doing heavy decoding in a widget or service extension. The memory limit is low and the kill is silent.

They might follow up with

  • How does a widget get fresh data? The app writes to a shared container and asks WidgetKit to reload its timelines.
  • Where do extensions get their time budget? From the system; a notification service extension, for example, has seconds to modify a payload.

Related questions

  • 6.1.1 What is the iOS process model, and what can an app process not do?
  • 6.8.1 What is an app group, and what can go wrong when an app and an extension share a database?
  • 6.6.2 What is jetsam, and how does it differ from a crash?

← How do keychain access groups differ from app groups?