Feature | Banners | Alerts | Badges |
Appearance | A temporary notification that appears at the top of the screen or on the Lock Screen. Contains a brief message. | A pop-up box that appears in the center of the screen, dimming the app interface behind it. | A small red circle with a number (or just a dot) that appears on the corner of an app's icon on the Home Screen. |
User Interaction | Passive & Optional. Banners disappear on their own after a few seconds. The user can swipe it away or tap it to open the app, but no immediate action is required. | Forced & Immediate. The user must interact with it by tapping one of the provided buttons (e.g., "OK," "Cancel") to dismiss the alert and resume using the app. | Indirect & Asynchronous. Requires no immediate interaction. It's a persistent, non-interruptive reminder that there is new content or information to see inside the app. |
Visibility | High but transient. It grabs attention for a moment but doesn't persist on the main screen (it can be found later in the Notification Center). | Highest possible. It is a modal view that takes over the screen and blocks all other interaction with the app until it is addressed. | Low but persistent. It is only visible on the Home Screen and does not interrupt the user's current task. It remains until the user opens the app and clears the condition that triggered it. |
Common Use Case | Informing the user of a new event, like a new message, an email, a news update, or the completion of a background task. | For critical actions, errors, or confirmations. Examples: confirming a purchase, warning of data loss, or system-level permission requests. | Indicating a count of unread items, such as unread emails, new social media mentions, or pending tasks in a to-do list. |
Level of Urgency | Low to Medium | High / Critical | Low / Informational |
Feature | Regular Notification | User-Silenced ("Deliver Quietly") | Developer's Silent Notification |
What it is | normal pushes | Focus, DND, mute mode, etc. | Background app refresh |
Banner Alert | Yes | No | No |
Lock Screen Alert | Yes | No | No |
Sound/Vibration | Yes | No | No |
Appears in Notification Center | Yes | Yes | No |
App Icon Badge | Yes | Yes (Optional) | No |
Visible to User? | Yes | Yes, but only if they look | No, never |
Feature | Service Extension (NSE) | Content Extension (NCE) |
Fetch external media (image/video) | ✅ | ❌ |
Modify text, localize, decrypt | ✅ | ❌ |
Custom layouts/UI for expanded push | ❌ | ✅ |
Needed for rich media | ✅ | Optional (but nice) |
Runs on every push? | ✅ (if mutable-content) | ❌ (only on expand) |
Platform | UI Context | Element | Recommended Visible Characters (Range) | Notes & Contextual Factors |
iOS / iPadOS | Banner Alert | Title | 25-50 | Highly constrained. The full message is rarely visible. |
Subtitle | ~30-60 | Often not displayed or heavily truncated. | ||
Body | ~60-80 (1-2 lines) | Only the first one or two lines are visible. | ||
Lock Screen / Notification Center (Collapsed) | Title | 30-60 | Varies with timestamp length and OS version (e.g., iOS 15 UI). | |
Subtitle | ~40-60 (1 line) | Provides a single line of secondary context. | ||
Body | ~110-170 (2-4 lines) | The core visible area for most notifications. | ||
Expanded View | Title | 30-60 | Remains a single line. | |
Subtitle | ~40-60 (1 line) | Remains a single line. | ||
Body | Up to ~250+ (7+ lines) | Reveals much more text. Presence of rich media reduces space. Payload is the ultimate limit. | ||
watchOS | Short-Look | Title | 20-40 | CRITICAL: The only text displayed. Must be a complete thought. subtitle and body are ignored. |
Subtitle | N/A | Not displayed. | ||
Body | N/A | Not displayed. | ||
Long-Look | Title | 20-40 | Full title is visible at the top of a scrollable view. | |
Subtitle | ~30-50 (1 line) | Visible below the title. | ||
Body | Full Payload | The entire body text (within the 4KB payload limit) is accessible in a scrollable view. | ||
macOS | Banner Alert | Title | 30-50 | More screen real estate, but brevity is still key. |
Subtitle | ~40-60 | Generally visible. | ||
Body | ~80-120 | More text is visible than on iOS banners, but still truncated. | ||
tvOS | All Contexts | Title | N/A | No user-visible text alerts are supported. |
Subtitle | N/A | Functionality is limited to app icon badging and silent background pushes. |
# | Vertical | Rich Elements Used | What the User Sees / Does | Why It’s Exciting |
1 | Clinical Workflow | Text-input field | “Patient John Smith’s dosage changed. Confirm?” → Nurse taps, types “Adjusted to 5 mg BID,” hits ✅. | Closes micro-tasks without opening the EHR—bye-bye context switching. |
2 | Smart Home Security | Toggle switch | “Motion detected near garage.” Expand → Arm/Disarm switch right there. | Turns a nervous moment into a one-tap fix from the lock screen. |
3 | E-commerce Fashion | Image carousel / animated GIF | “New arrivals just dropped!” Swipe color variants, tap Add to Bag. | Visual dopamine + zero app latency → higher impulse buys. |
4 | Telehealth Follow-up | Inline video clip (≤30 s) | “Dr Patel: wound-care demo.” Patient watches mini-video, taps Acknowledge. | Boosts adherence; no hunting for the video inside the portal. |
5 | Home Security | Static map view | “Glass break — Backyard.” Map pin shows exact sensor spot. | Instant geography context—vital when managing multiple properties. |
6 | Voice-Messaging / Chat | Audio attachment + play/pause + text input | “🎤 New voice note from Maria.” Expand → 15-sec audio auto-plays; reply button below. | Lets users triage messages hands-free; keeps WhatsApp-style flow alive. |
7 | Baby-Monitor / Smart-Cam Alert | Audio clip + snapshot | “Baby stirred at 02:14.” Thumbnail + cry audio; tap Open Live Feed. | Parents know if it’s a real scream or a sleepy whimper—fast. |
8 | Guided Meditation / Fitness | Audio intro + quick-start button | “2-min Mindful Break ready.” Expand → soothing chime starts; Begin Session button logs the workout. | Turns idle moments (elevator, queue) into wellness reps—friction-free. |
9 | Fintech / Stock-Trading | Live sparkline, +/- ticker, “Buy / Sell” buttons | “$NVDA just hit $150 (+3.4%).” A tiny sparkline animates; buttons let the user fire a market-order in one tap. | Converts FOMO into instant trades without app load time. |
10 | EdTech Micro-Learning | Inline quiz card + text input | “Spanish Sprint: Translate ‘apple’.” A text field takes the answer; success animation pops. | Turns dead time (lock-screen) into spaced-repetition wins. |
11 | SaaS DevOps / On-Call | Log snippet + “Ack / Snooze” switches | “CPU spike on api-prod-3.” Expand to skim the highlighted log lines; toggle Snooze 15 min or Ack. | Saves bleary-eyed engineers a midnight app dive. |
12 | Auction / Flash-Sale Platforms | Countdown timer | “Lot 27 closes in 00:01:59.” A live countdown ticks; place a bid by choosing one of the options | Captures impulse bids while urgency is red-hot. |
13 | Healthcare RPM (Remote Patient Monitoring) | Vitals chart (mini line-graph) + call button | “Mrs. Chen’s BP spiked to 165/98.” Clinician expands to view a 24-h chart and taps Call to start a session. | Lets care teams intervene faster than EHR alerts alone. |
14 | Travel / Hotel Concierge | Room-upgrade carousel + “Select” buttons | “Last-minute suite upgrade -50%.” Swipe photos; tap Book to lock it in. | Drives high-margin upsells during peak excitement. |
15 | IoT Industrial / Field Service | Live camera thumbnail + toggle | “Pump #4 vibration anomaly.” Thumbnail autoplay of the on-site camera; toggle Shut Pump. | Cuts mean-time-to-mitigation when every minute costs money. |
16 | Interactive Polls / Social Engagement | Radio buttons + vote count + custom ocean wave sound | “Weekend plan? 🏖️/🎢/📚” Choose and see live percentages update. | Sky-high engagement for community-driven apps. |
17 | Post-Service Feedback (ride-share, food delivery, customer support) | Five-star buttons (interactive controls) | “How was your experience with Alex?” Five tappable star icons appear; user taps ★★★★☆, optional comment box slides down. | Harvests fresh, high-quality feedback without forcing an app hop—response rates skyrocket. |
Rich element | Extra iOS hours¹ | When it blows up |
Image (PNG/JPEG) | +8 – 12h | Huge files, dark-mode variants |
Animated GIF / image seq. | +10 – 16h | Frame count & memory limits |
Audio | +12 – 18h | Custom controls, background quirks |
Video | +16 – 24h | HLS vs. MP4 fallback, autoplay rules |
Map snapshot | +20 – 30h | Live ETA refresh, geofencing |
Carousel (3–5 imgs) | +24 – 40h | Extra buttons, tap-tracking |
Text-input field | +12 – 20h | Localization-ready, validation, secure text. |
Interactive controls (buttons, toggles, timers) | +16 – 32h | Backend state sync, analytics |
Action Buttons
Complete List of Possible Interactive Controls
Control | Supported User Interactions | Technical Limitations & Considerations |
Buttons (UIButton) | Tap: The most common interactive element. Can trigger background tasks or open the app to a specific screen. | Fully supported. Can be styled with text, icons, and custom backgrounds. Can trigger actions that require authentication. |
Switches (UISwitch) | Toggle: Allows for simple on/off state changes (e.g., enabling or disabling a setting). | The state change can be handled within the notification extension. The visual state of the switch can be updated immediately. |
Text Fields (UITextField) | Type: Users can input short text directly into the notification. This requires the system keyboard to be presented. | The text field must be configured to work with the limited lifecycle of the notification. Keyboard management can be complex. The UNTextInputNotificationAction is an alternative for simpler text input via an action button. |
Steppers (UIStepper) | Tap: Users can tap the increment or decrement buttons to change a numerical value. | Each tap is a discrete event, making this a viable control. The associated value can be displayed in a UILabel and updated with each tap. |
Segmented Controls (UISegmentedControl) | Tap: Allows the user to select one option from a few choices. | A good way to offer a limited set of mutually exclusive options. The selection change is a discrete event that can be handled by the extension. |
Checkboxes (Custom UIButton) | Tap: For selecting or deselecting items in a list. Implemented using a UIButton with different state images. | While there's no standard UICheckbox, a UIButton can be easily configured to function as one, toggling between selected and deselected states on tap. |
Most Common Live Activities Use Cases
Category | Use Case | Real-Time Updates | Example Apps |
Delivery & Transportation | Food/package tracking | Driver location, ETA, order status | Uber, DoorDash, Instacart |
Rideshare journey | Route progress, driver details, fare | Lyft, Uber | |
Sports & Gaming | Live game scores | Score changes, player stats, time remaining | ESPN, TheScore |
Fantasy sports | Point updates, player performance | DraftKings, FanDuel | |
Travel | Flight status | Gate changes, delays, boarding time | Flighty, FlightRadar24 |
Transit directions | Next stop, arrival time, transfers | Citymapper, Transit | |
Fitness & Health | Workout tracking | Duration, heart rate, calories, pace | Strava, Nike Run Club |
Medication reminders | Countdown timer, dose tracking | Medisafe | |
Commerce & Services | Parking meters | Time remaining, expiry alerts | ParkWhiz, SpotHero |
Queue/wait times | Position in line, estimated wait | Disney, DMV apps | |
Productivity | Timer/stopwatch | Elapsed time for tasks, pomodoro | Toggl, Forest |
Task progress | Steps completed, time remaining | Todoist, Things | |
Entertainment | Live audio/podcast | Now playing, progress, controls | Spotify, Overcast |
Event countdowns | Time until concert, ticket info | StubHub, Ticketmaster |
Scenario | Typical use-case scope | Total effort (hours) |
Simple – local-only timer | In-app start/stop, no server | 40 – 64h |
Moderate – food-delivery / ride-share tracker | One activity per user, server pushes images & status | 280 – 360h |
Complex – multi-game sports board | High-freq updates, dynamic assets, multiple concurrent activities, broadcast channels | 480 – 640h |
Phase | What founders / PMs should insist on | Key API / payload knobs | Why it matters |
1. Detect | App watches connectivity with NWPathMonitor and, the moment status == .unsatisfied, fires a local activity.update() marking the UI “offline.” | NWPathMonitor, Activity.update() | Users see the loss of data instantly instead of waiting for a timeout. |
2. Degrade | The same update also shortens staleDate (e.g., now + 120 s). If the app is later suspended, ActivityKit will flip the widget to its built-in .stale state and show a “Last updated…” stamp. | stale-date field in payload | Guarantees the Live Activity never freezes with ancient data. |
3. Recover / Dismiss | Server keeps sending full-state snapshots (APNs stores only one per device) and, when the event ends, ships an event:"end" push with: • dismissal-date = past timestamp → instant removal • apns-expiration long enough to survive short outages | event, dismissal-date, apns-expiration headers | Ensures the activity cleans itself up—even if the phone was offline when the event finished. |
4. Clean-up safety net | On every app launch, code loops through Activity.activities, asks the backend for ground truth, and ends any “zombie” activities it finds. | Activity.activities | Catches the rare cases where the final push was missed or expired. |
# | Action item |
1 | Throttle your pings. Default to low-priority (apns-priority 5) updates and reserve high (10) for time-critical moments; exceed the budget and iOS throttles you automatically. |
2 | Pick the right priority header (5 vs 10). The header controls delivery latency and your update budget. |
3 | Attach a relevance-score (0–1). Higher scores float your Live Activity to the top of the Lock Screen or Dynamic Island when several are active. |
4 | Set a stale-date. If the device misses pushes, iOS flips to your “stale” UI instead of showing wrong data. |
5 | Use broadcast pushes (iOS 18+). For one-to-many cases (e.g., a game score) send a single update to a channel—APNs fans it out to every subscriber. |
6 | Handle pushTokenUpdates. Each Live Activity’s push-to-update token can rotate; listen for changes and replace the old token on your server. |
7 | Design layouts per context. Craft distinct SwiftUI views for Lock Screen, Dynamic Island (compact/expanded), and StandBy—don’t recycle a notification card. |
8 | Show “last updated” or offline states. Pair stale-date with a visual cue so users know data may be out of date. |
# | Best practice | Why it matters | How to implement (one-liner) |
1 | Keep an offline queue. | APNs stores only one pending notification per app while a device is offline—extra alerts overwrite the first one in the queue. | Maintain a small FIFO queue keyed by device-token + bundle ID and flush it when the first push is accepted. Dev Handoff |
2 | Collapse follow-ups. | Users hate “notification machine-gun” bursts, and you pay for them. | Set the same apns-collapse-id (e.g., order-123) on every update so APNs shows only the freshest payload. |
3 | Render instantly. | Notification Content Extensions get ≈200 ms; slow setups delay delivery or show blank UI. | Pre-cache assets locally—no network calls inside didReceive(_:withContentHandler:). |
4 | Template by category. | Reminders and reports shouldn’t share the same UI. | Assign a unique categoryIdentifier and ship a dedicated Content Extension for each template. |
5 | Hide default clutter. | Duplicated system text under your custom view looks sloppy. | In the extension’s Info.plist, set UNNotificationExtensionDefaultContentHidden = YES. |
6 | Test with Push Notifications Console. | Early, real-device tests catch token errors and bad layouts before App Review does. | Use Apple’s web console to send and inspect pushes to any TestFlight device. Dev Handoff |
7 | Update in place. | Order status changed? Replace, don’t stack. | Resend the push with the same apns-collapse-id (and, if relevant, the same category) to overwrite the previous card. |
8 | Treat a push as a signal, not state. | APNs may drop, reorder, or collapse messages—relying on every notification breaks the user’s view of reality. | The correct approach is to ensure the final notification in a sequence updates the app's badge corewrote the card descriptionsunt accurately, and that upon opening the app, a full, up-to-date state is fetched from the server. |