Snippets

Small SwiftUI patterns I keep around for platform-aware interfaces, navigation, sharing, and presentation.

Put platform-specific controls in the safe area

SwiftUI · cross-platform layout

struct EditorShell: View {
    #if os(visionOS)
    var body: some View {
        TextEditor(text: $draft)
            .ornament(
                visibility: .visible,
                attachmentAnchor: .scene(.bottom)
            ) {
                Button("Close") { dismiss() }
            }
    }
    #else
    var body: some View {
        TextEditor(text: $draft)
            .safeAreaInset(edge: .bottom) {
                Button("Close") { dismiss() }
                    .frame(maxWidth: .infinity)
            }
    }
    #endif
}

Run a side effect when a tab is selected

SwiftUI · state and bindings

enum Tab: Hashable {
    case library
    case settings
}

struct RootView: View {
    @State private var tab = Tab.library

    var body: some View {
        TabView(selection: Binding(
            get: { tab },
            set: { nextTab in
                if nextTab == .settings { presentComposer() }
                tab = nextTab
            }
        )) {
            LibraryView().tag(Tab.library)
            SettingsView().tag(Tab.settings)
        }
    }
}

Make a remote image shareable

Swift · Transferable

struct RemoteImage: Transferable {
    let data: Data

    static var transferRepresentation: some TransferRepresentation {
        DataRepresentation(exportedContentType: .png) { image in
            image.data
        }
    }
}

func loadImage(from url: URL) async throws -> RemoteImage {
    let (data, _) = try await URLSession.shared.data(from: url)
    return RemoteImage(data: data)
}

Keep an AppDelegate in a SwiftUI app

SwiftUI · app lifecycle

@main
struct ReaderApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self)
    private var appDelegate

    var body: some Scene {
        WindowGroup { LibraryView() }
    }
}

final class AppDelegate: NSObject, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions options: [UIApplication.LaunchOptionsKey: Any]? = nil
    ) -> Bool {
        configureAudio()
        return true
    }
}

Drive NavigationStack with a typed route

SwiftUI · navigation

enum Route: Hashable {
    case document(UUID)
    case settings
}

struct AppShell: View {
    @State private var path: [Route] = []

    var body: some View {
        NavigationStack(path: $path) {
            LibraryView()
                .navigationDestination(for: Route.self) { route in
                    switch route {
                    case .document(let id): ReaderView(documentID: id)
                    case .settings: SettingsView()
                    }
                }
        }
    }
}

Present a focused settings sheet

SwiftUI · presentation

struct LibraryToolbar: View {
    @State private var showingSettings = false

    var body: some View {
        Button("Settings") { showingSettings = true }
            .sheet(isPresented: $showingSettings) {
                SettingsView()
                    .presentationDetents([.medium])
                    .presentationBackground(.thinMaterial)
                    .presentationCornerRadius(24)
            }
    }
}

Use let for values that should not drift

Swift basics · mutability

struct ReaderSettings {
    let documentID: UUID
    var speed: Double
}

var settings = ReaderSettings(documentID: documentID, speed: 1.0)
settings.speed = 1.25
// settings.documentID = anotherID // Compile-time error

Choose if let or guard let for optional values

Swift basics · optionals

func titleUsingIf(_ document: Document?) -> String {
    if let document { return document.title }
    return "Untitled"
}

func titleUsingGuard(_ document: Document?) -> String {
    guard let document else { return "Untitled" }
    return document.title
}

Remove duplicates without losing order

Swift basics · collections

func uniquePreservingOrder<T: Hashable>(_ values: [T]) -> [T] {
    var seen = Set<T>()
    return values.filter { seen.insert($0).inserted }
}

let chapters = uniquePreservingOrder(["intro", "setup", "intro"])
// ["intro", "setup"]

Treat string-to-number conversion as fallible

Swift basics · type conversion

func parseCount(_ text: String) -> Int? {
    Int(text.trimmingCharacters(in: .whitespacesAndNewlines))
}

if let count = parseCount("42") {
    print("Loaded \(count) items")
}

Sort models by the property people read

Swift basics · sorting

struct Book {
    let title: String
}

let sortedBooks = books.sorted {
    $0.title.localizedCaseInsensitiveCompare($1.title)
        == .orderedAscending
}