iOS 27 brings meaningful updates to Live Activities and the Dynamic Island, including richer layout options, improved gesture support, and expanded configuration APIs that give developers more control over how their activities appear and behave in the Dynamic Island and on the Lock Screen.
⢠New `.supplementalActivityFamilies` modifier allows a single ActivityConfiguration to declare support for additional layout regions introduced in iOS 27
⢠`ActivityContent.staleDate` handling is stricter ā activities not updated before stale date are now visually dimmed in the Dynamic Island automatically
⢠Expanded Dynamic Island region now supports SwiftUI `Button` with `.borderedProminent` style for primary CTA directly inside the island
⢠`ActivityAuthorizationInfo.areActivitiesEnabled` is supplemented by a new async stream API for observing authorization changes in real time
⢠New expanded Dynamic Island layout regions let apps surface richer, more interactive content without requiring the user to force-expand the island
⢠Improved gesture APIs allow taps and swipes within Dynamic Island presentations to trigger in-app actions directly
⢠Enhanced ActivityKit configuration options provide finer-grained control over update policies, relevance scoring, and dismissal behavior
Demonstrates creating a Live Activity with a Dynamic Island expanded layout showing a delivery progress bar and an interactive button, using the updated iOS 27 ActivityKit and WidgetKit APIs.
import ActivityKitimport SwiftUIimport WidgetKitā// Pre-iOS 27 approach ā no Button with AppIntent inside Dynamic Island expanded bottomā// Buttons inside Dynamic Island were limited to Link/URL-based deep links onlyā+// MARK: - Attributesstruct DeliveryAttributes: ActivityAttributes {public struct ContentState: Codable, Hashable {var statusMessage: Stringvar progressFraction: Doublevar estimatedMinutes: Int}var orderNumber: String}+// MARK: - Widget Extension: Live Activity Viewstruct DeliveryLiveActivityView: Widget {var body: some WidgetConfiguration {ActivityConfiguration(for: DeliveryAttributes.self) { context in+ // Lock Screen / Banner UIHStack {Image(systemName: "shippingbox.fill").foregroundStyle(.orange)VStack(alignment: .leading) {Text(context.state.statusMessage).font(.headline)ProgressView(value: context.state.progressFraction).tint(.orange)}Spacer()Text("\(context.state.estimatedMinutes)m").font(.caption).foregroundStyle(.secondary)}.padding().activityBackgroundTint(.black.opacity(0.8))} dynamicIsland: { context inDynamicIsland {+ // Expanded regionsDynamicIslandExpandedRegion(.leading) {Image(systemName: "shippingbox.fill").foregroundStyle(.orange).font(.title2)}DynamicIslandExpandedRegion(.trailing) {Text("\(context.state.estimatedMinutes)m").font(.caption).foregroundStyle(.secondary)}DynamicIslandExpandedRegion(.center) {Text(context.state.statusMessage).font(.headline).lineLimit(1)}DynamicIslandExpandedRegion(.bottom) {VStack(spacing: 8) {ProgressView(value: context.state.progressFraction).tint(.orange)ā // Pre-iOS 27: had to use Link for navigation, no AppIntent buttonā Link(destination: URL(string: "myapp://track")!) {+ // iOS 27: Button with borderedProminent inside expanded island+ Button(intent: TrackDeliveryIntent()) {Label("Track Order", systemImage: "location.fill")}ā .foregroundStyle(.orange)+ .buttonStyle(.borderedProminent)+ .tint(.orange)}}} compactLeading: {Image(systemName: "shippingbox.fill").foregroundStyle(.orange)} compactTrailing: {Text("\(context.state.estimatedMinutes)m").font(.caption2)} minimal: {Image(systemName: "shippingbox.fill").foregroundStyle(.orange)}}}+}++// MARK: - Starting a Live Activity+func startDeliveryActivity(orderNumber: String) throws {+ let attributes = DeliveryAttributes(orderNumber: orderNumber)+ let initialState = DeliveryAttributes.ContentState(+ statusMessage: "Order picked up",+ progressFraction: 0.2,+ estimatedMinutes: 30+ )+ let content = ActivityContent(+ state: initialState,+ staleDate: Date.now.addingTimeInterval(300)+ )+ let activity = try Activity.request(+ attributes: attributes,+ content: content,+ pushType: .token+ )+ print("Started activity: \(activity.id)")}
Live Activity updates via push (ActivityKit push updates) still require a valid APNs token and entitlement; stale date and relevance score must be set carefully or iOS may deprioritize updates. Dynamic Island compact/minimal/expanded states must all be provided ā omitting any will cause a runtime warning in Xcode 16+.
Dynamic Island UI only appears on iPhone 14 Pro and later; Lock Screen Live Activities work on all supported devices running iOS 27+
More iOS 27 APIs land every week.
Get notified when new capabilities are published ā no noise, just signal.