What's New in SwiftUI for iOS 27

blakec1 pts0 comments

What's New in SwiftUI for iOS 27

Skip to content

English

English

简体中文

繁體中文

Français

Deutsch

日本語

한국어

Polski

Português

Español

English

简体中文

繁體中文

Français

Deutsch

日本語

한국어

Polski

Português

Español

What's New in SwiftUI for iOS 27

June 08, 2026<br>22 min read

swiftui

ios

ios-27

swift

apple

Every SwiftUI release tells you where the framework&rsquo;s pressure points were by what Apple decided to rebuild. iOS 27&rsquo;s answer is unusually broad: lists get first-class reordering, documents get a new reader/writer protocol family, toolbars get an overflow model with explicit priority, and error presentation finally gets a binding you can hand an Error directly. The release moves four surfaces at once, and most apps touch at least two of them.1

The temptation with a release this wide is to adopt everything. The better move is to recognize which additions change how you build versus which are convenience overloads on patterns you already use. Drag-to-reorder and the document protocols are the former: they replace code you wrote by hand. Item-based alerts and AsyncImage(request:) are the latter: they remove a workaround. This post sorts the iOS 27 SwiftUI surface into those threads, with the real declarations and the reasoning for when each one earns its place in your code.

TL;DR / Key Takeaways

Lists and custom containers get declarative reordering: reorderContainer(for:isEnabled:move:) marks a container, reorderable() on DynamicViewContent opts the rows in, and you receive a ReorderDifference instead of writing index-math by hand.23

Lazy drag containers arrive through dragContainer(for:itemID:in:_:) plus draggable(containerItemID:containerNamespace:), which carries only an identifier so the framework fetches payloads lazily when a drag starts.45

A new document model lands as ReadableDocument and WritableDocument (with DocumentReader/DocumentWriter doing the on-disk work and FileWrapperDocumentReader/FileWrapperDocumentWriter for the simple case), backed by URLDocumentConfiguration.6789101112

Toolbars gain ToolbarOverflowMenu, the topBarPinnedTrailing placement, and visibilityPriority(_:), so you decide which controls survive when the bar runs out of room.131415

Error presentation gets alert(error:actions:message:) and item-based alert(_:item:actions:) / confirmationDialog, plus AsyncImage(request:) for full URLRequest control and asyncImageURLSession(_:) to share a session.1617181920

Rounding out the surface: swipeActions(...onPresentationChanged:), swipeActionsContainer(), NavigationTransition.crossFade, TabRole.prominent, UIHostingSceneDelegate, and GestureInputKinds.212223242526

Drag-To-Reorder Becomes Declarative

Reordering a list in SwiftUI used to mean onMove, an index set, and a destination offset you translated into your own model mutation. iOS 27 replaces that with a two-part declaration: you mark a container as reorderable, and you mark its content as participating. The container then hands you a structured diff.

The single-collection case is the common one. You declare reorderContainer(for:isEnabled:move:) on the container and reorderable() on the DynamicViewContent inside it:23

struct LandmarkList: View {<br>@State private var landmarks: [Landmark]

var body: some View {<br>List {<br>ForEach(landmarks) { landmark in<br>LandmarkRow(landmark: landmark)<br>.reorderable()<br>.reorderContainer(for: Landmark.self) { difference in<br>// Apply the reorder to your model.<br>landmarks.apply(difference)

The signature tells you the contract. The container modifier is generic over Item : Identifiable and gives you a ReorderDifference:2

nonisolated func reorderContainerItem>(<br>for item: Item.Type,<br>isEnabled: Bool = true,<br>move: @escaping (ReorderDifferenceItem.ID, ReorderableSingleCollectionIdentifier>) -> ()<br>) -> some View where Item : Identifiable, Item.ID : Sendable

Two design decisions matter here. First, the framework drives the interaction: as Apple&rsquo;s documentation describes it, a reorderable item can be lifted with a drag gesture, a placeholder view takes its position to show where the item will land, and the placeholder tracks the drag through the container.2 You no longer build that affordance; you describe the collection and react to the result. Second, isEnabled is a parameter rather than a separate modifier, so an edit-mode toggle becomes one boolean instead of conditional view construction.

When a container holds more than one collection, you reach for the overload that takes a collection identifier type, reorderContainer(for:in:isEnabled:move:):27

nonisolated func reorderContainerItem, CollectionID>(<br>for item: Item.Type,<br>in collectionID: CollectionID.Type,<br>isEnabled: Bool = true,<br>move: @escaping (ReorderDifferenceItem.ID, CollectionID>) -> ()<br>) -> some View where Item : Identifiable, CollectionID : Hashable, CollectionID : Sendable, Item.ID : Sendable

The ReorderDifference is now keyed by both the item ID and a collection ID, so a move that crosses from one section into another...

item swiftui move container drag isenabled

Related Articles