What's new in SwiftUI
SwiftUI 2026 updates for Liquid Glass, document apps, reorderable containers, toolbar control, AsyncImage caching, @State, and ContentBuilder.
TL;DR
- Apps built for the 2027 releases automatically adopt the refreshed Liquid Glass appearance, with new controls for active-window styling, prominent tabs, toolbar overflow, pinned toolbar items, and minimize-on-scroll behavior.
- SwiftUI's expanded document APIs add creation sources, WritableDocument/ReadableDocument, snapshot-based writing, background DocumentWriter/DocumentReader work, progress reporting, and multi-format export such as PNG.
- New interaction APIs support reordering in List, LazyVGrid, and other containers, swipe actions outside List via swipeActionsContainer(), and item-binding confirmation dialogs and alerts.
- Performance improvements include default HTTP caching for AsyncImage, customizable URLRequest/URLSession support, lazy initialization for @State-stored Observable classes, and faster type checking through ContentBuilder.
Refreshed look, resizability, and toolbars
SwiftUI apps built for the 2027 releases automatically receive the updated Liquid Glass appearance. Liquid Glass responds to the system tint slider, custom Liquid Glass elements can be marked interactive on macOS, and iPad apps get inactive-window dimming similar to Mac.
The session emphasizes testing resizable layouts in Xcode 27 Live Previews, which now include resize handles. Apps that mix UIKit and SwiftUI should prefer size classes and correct screen-geometry handling instead of relying on idiom-based assumptions.
- Use the appearsActive environment value to adjust custom UI when a window is inactive.
- Use .labelStyle(.titleAndIcon) to opt important menu items into showing icons in menu bars that otherwise minimize icon use.
- Use Tab(role: .prominent) for a visually distinct tab such as a cart or primary destination.
- Use toolbar visibility priority, ToolbarOverflowMenu, and topBarPinnedTrailing to control what remains visible when toolbar space is constrained.
- Use toolbarMinimizeBehavior(.onScrollDown, for: .navigationBar) to reclaim vertical space while scrolling.
Keep important toolbar actions visible
Prioritize editing actions, force infrequent actions into overflow, and pin Share so it is not hidden at narrow sizes.
StickerPageView()
.toolbar {
ToolbarItemGroup {
UndoButton()
RedoButton()
}
.visibilityPriority(.high)
ToolbarOverflowMenu {
ChoosePhotoButton()
ExportAsImageButton()
ClearAllStickersButton()
}
ToolbarItem(placement: .topBarPinnedTrailing) {
ShareButton()
}
}Minimize the navigation toolbar while scrolling
Lets the system move the navigation bar out of the way as content scrolls down.
ScrollView {
StickerListView()
}
.toolbarMinimizeBehavior(.onScrollDown, for: .navigationBar)Document-based app APIs
SwiftUI's document model is expanded for the 2027 releases. A document app still starts from a DocumentGroup, and the document object can use Observation so dependent views update only when the properties they read change.
DocumentCreationSource lets an app expose multiple creation paths in a launch scene. The chosen source is passed through the document creation context, enabling flows such as creating a blank document or creating one from a photo and immediately presenting a photo picker.
- Declare custom DocumentCreationSource values and attach them to NewDocumentButton instances.
- Use the DocumentGroup creation closure's context parameter to initialize the document differently for each source.
- Adopt WritableDocument to describe writable content types, create an immutable snapshot, and provide a DocumentWriter.
- Adopt ReadableDocument for the corresponding read path, with disk work handled by a DocumentReader.
- Add more writable content types, such as .png, and branch in the writer based on UTType conformance.
Custom document creation sources
Expose multiple new-document buttons and pass the selected source into document initialization.
@main
struct Stickers: App {
var body: some Scene {
DocumentGroupLaunchScene("Create a Sticker Page") {
NewDocumentButton("New Sticker Page", source: .blank)
NewDocumentButton("Sticker Page from Photo...", source: .photo)
}
DocumentGroup { document in
StickerPageDocumentView(document)
} newDocument: { configuration, context in
StickerPageDocument(configuration: configuration, context: context)
}
}
}
extension DocumentCreationSource {
static let blank = Self(id: "blank")
static let photo = Self(id: "photo")
}Snapshot-based writable document
The writer runs asynchronously and nonisolated, can diff against the previous snapshot, and can report progress while writing.
@Observable
final class StickerDocument: WritableDocument {
static let writableDocumentTypes: [UTType] = [.stickerDocument]
@MainActor
func snapshot(contentType: UTType) async throws -> sending PageSnapshot {
makeSnapshot()
}
func writer(configuration: sending WriteConfiguration) -> sending Writer {
Writer(contentType: configuration.contentType)
}
}
struct Writer: DocumentWriter {
typealias Snapshot = PageSnapshot
let contentType: UTType
nonisolated func write(
snapshot: sending PageSnapshot,
to destination: URL,
previous: sending PageSnapshot?,
progress: consuming Subprogress
) async throws {
// Compare snapshot and previous, report progress, and write to disk.
}
}Reordering, swipe actions, and presentations
Reorderable containers let users drag to rearrange items in List, LazyVGrid, and other SwiftUI containers. SwiftUI handles the drag interaction and animations; the app receives a ReorderDifference and applies it to its data source.
Swipe actions are no longer limited to List. A scroll view with a LazyVStack can coordinate row swipe actions by adding swipeActionsContainer(). Confirmation dialogs and alerts also gain the item-binding pattern familiar from sheets.
- Add .reorderable() to the repeated item content and .reorderContainer(for:) to the containing view.
- Use the ReorderDifference to update the backing collection; the sample helper uses OrderedDictionary from Swift Collections.
- Reordering is available for watchOS for the first time through these APIs.
- Use .swipeActions on arbitrary row views and .swipeActionsContainer() on the containing scroll area.
- Use confirmationDialog(:item:) or alert(:item:) when presentation should be driven by an optional selected model value.
Reorder a list or grid
The same reorderable API pattern works across different containers.
List {
ForEach(stickers) { sticker in
StickerListItemView(sticker: sticker)
}
.reorderable()
}
.reorderContainer(for: Sticker.self) { difference in
difference.apply(to: &stickers)
}
LazyVGrid(columns: columns) {
ForEach(stickers) { sticker in
StickerListItemView(sticker: sticker)
}
.reorderable()
}
.reorderContainer(for: Sticker.self) { difference in
difference.apply(to: &stickers)
}Swipe actions outside List
Coordinates swipe actions for custom scrollable layouts.
ScrollView {
LazyVStack {
ForEach(stickers) { sticker in
StickerListItemView(sticker: sticker)
.swipeActions {
DeleteButton(sticker: sticker)
}
}
}
}
.swipeActionsContainer()AsyncImage and @State performance
AsyncImage now supports standard HTTP caching by default, respecting server cache headers without app changes. Apps built with Xcode 27 can customize image loading by supplying a URLRequest and by configuring the URLSession used by AsyncImage.
@State has been converted from a DynamicProperty to a macro. When an Observable class is initialized into @State, SwiftUI now initializes it lazily and only once for the lifetime of the view instead of creating and discarding new instances on repeated view initialization. This behavior is back-ported to the OS releases where @Observable first appeared, starting with iOS 17, macOS 14, and aligned releases.
- Use URLRequest for per-request behavior such as cachePolicy.
- Use asyncImageURLSession(_:) with a custom URLSession and URLCache for longer-lived download configuration.
- If a @State property has a default value and is also assigned in init, remove the default value to avoid the new macro initialization error.
Customize AsyncImage caching
Use a request-level cache policy and a custom session cache for AsyncImage downloads.
@Observable
class StickerStore {
static let imageSession: URLSession = {
let config = URLSessionConfiguration.default
config.urlCache = URLCache(
memoryCapacity: 64 * 1024 * 1024,
diskCapacity: 256 * 1024 * 1024
)
return URLSession(configuration: config)
}()
}
ForEach(pets) { pet in
AsyncImage(request: URLRequest(
url: pet.imageURL,
cachePolicy: .returnCacheDataElseLoad
))
}
.asyncImageURLSession(StickerStore.imageSession)Fix @State macro initialization
When assigning @State in init, omit the default value from the property declaration.
struct StickerPageView: View {
@State private var page: StickerPage
let title: String
init(title: String) {
self.page = StickerPage(title: title)
self.title = title
}
var body: some View { /* ... */ }
}ContentBuilder and agent skills
SwiftUI improves compile-time performance for complex nested views by unifying common builders under ContentBuilder. This reduces overload search paths for common constructs such as Section, Group, and ForEach, helping avoid expensive type-checking in large view expressions.
ContentBuilder is an evolution of ViewBuilder and can be used with any minimum deployment target when building with Xcode 27. Xcode 27 also includes SwiftUI agent skills: a SwiftUI Specialist Skill for best practices and a What's New in SwiftUI Skill for adopting the 2027 APIs.
- Use @ContentBuilder for builder functions that assemble SwiftUI content.
- Build with Xcode 27 to get the type-checking improvements even when targeting earlier OS releases.
- Agent skills are available in the Xcode 27 Coding Assistant and can be exported for other tools with xcrun agent skills export.
Use ContentBuilder
ContentBuilder provides a unified builder path for SwiftUI content.
@ContentBuilder
func stickerLibraryView() -> some View {
// ...
}Export Xcode agent skills
Exports the Xcode 27 agent skills as Markdown files that can be imported into other workflows.
xcrun agent skills exportResources
Related Sessions
Swift Group Lab
Online WWDC26 Swift group lab for asking Apple engineers and designers questions about the week's major Swift announcements.
Code-along: Build powerful drag and drop in SwiftUI
Build SwiftUI drag-and-drop interactions with reorderable content, multi-item drag containers, preview formations, and move-aware drop configuration.