The iOS 15 SwiftUI release filled most of the long-standing gaps: list styling, swipe actions, pull to refresh, search, remote images, focus, drawing, and materials. Everything below is iOS 15 and macOS 12 and up.
List Upgrades
Separator styling and swipe actions arrived as modifiers.
Text(message)
.listRowSeparatorTint(.red)
.listRowSeparator(.visible, edges: .all)
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
Button("Remove", role: .destructive) {
messages.removeAll { $0 == message }
}
}
ButtonRole (.destructive, .cancel) styles the action; listSectionSeparator and
listSectionSeparatorTint cover section separators.
Refresh and Search
List { /* rows */ }
.refreshable { await reload() }
.searchable("Search term", text: $query, placement: .automatic)
refreshable attaches the pull-to-refresh gesture; searchable wires the system search
field into the navigation chrome.
AsyncImage and Markdown Text
AsyncImage(url:) downloads and shows a remote image through URLSession. Text accepts
the new AttributedString, and markdown works in string literals too:
Text("**Happy WWDC21**").
FocusState
First-responder control on iOS at last. Bind an optional field enum with @FocusState and
mark each field with focused(_:equals:); setting the state moves the keyboard focus.
enum Field: Hashable { case usernameField, passwordField }
@FocusState private var focusedField: Field?
TextField("Username", text: $username)
.focused($focusedField, equals: .usernameField)
SecureField("Password", text: $password)
.focused($focusedField, equals: .passwordField)
Button("Sign In") {
if username.isEmpty { focusedField = .usernameField }
else if password.isEmpty { focusedField = .passwordField }
else { handleLogin(username, password) }
}
Canvas, Materials, TimelineView
Canvas { context, size in ... }is the GPU-accelerateddrawRectequivalent for paths, images, and text.- Materials bring the system blur surfaces:
.background(.regularMaterial), from ultra-thin to ultra-thick. TimelineView(PeriodicTimelineSchedule(from: start, by: 1))re-renders on a schedule you define, for clocks and workout timers.
Also new: Accessibility Rotors and SectionedFetchRequest for Core Data.