Articles Projects About Subscribe
← All issues Newsletter

iOS Dev Weekly — Issue #44

Opening

Converting completion-style fetches to structured concurrency or migrating view state to @Observable often surfaces runtime issues: leaked child Tasks, unexpected renders, or navigation state that behaves differently than before. These problems show up under real user interaction, not in a contrived demo, so treat the work as behavioral refactoring and validate runtime invariants early.


This Week’s Big Story

SwiftUI Changes From WWDC 2026 Worth Adopting Now

WWDC 2026 introduced several SwiftUI features that are safe to adopt today—but the migration surface is behavioral, not just syntactic. Expect cancellation, invalidation, and restoration edges to change how screens behave under stress. Read on for concrete patterns to adopt and the tests you should add before flipping switches in production.


Trend Signals

• Sweet Jeebus, macOS 27 Golden Gate Removes the Dumb Icons from Menu Items — UI micro-details still matter to platform fidelity and developer expectations. [Source: HackerNews]

• Apple didn’t revolutionize power supplies; new transistors did (2012) — a reminder that platform shifts are often driven by low-level advances, not headline features; compatibility and incremental testing remain crucial. [Source: HackerNews]

• Announcing the Networking Workgroup — the Swift ecosystem is formalizing community work on networking, which could influence future async patterns and libraries you rely on. [Source: Swift.org Blog]


Swift Snippet of the Week

import SwiftUI
import Observation
import Foundation

@Observable @MainActor class SearchViewModel {
    var query: String = ""
    var results: [String] = []
    var isLoading: Bool = false

    func refresh() async {
        isLoading = true
        let currentQuery = query
        do {
            let fetched = try await fetchResults(for: currentQuery)
            guard !Task.isCancelled else { isLoading = false; return }
            if currentQuery == query { results = fetched }
        } catch {
            if !Task.isCancelled { results = [] }
        }
        isLoading = false
    }

    private func fetchResults(for q: String) async throws -> [String] {
        try await Task.sleep(nanoseconds: 300_000_000)
        return q.isEmpty ? [] : (1...5).map { "\(q) result \($0)" }
// … (truncated for newsletter)

This pattern matters because it couples view-observable state with explicit cancellation and identity checks, which avoids stale results and subtle flapping during rapid input or view lifecycle changes.


Community Picks

Sweet Jeebus, macOS 27 Golden Gate Removes the Dumb Icons from Menu Items — A small UI change that highlights how consistent platform styling affects app polish and user expectations.

Apple didn’t revolutionize power supplies; new transistors did (2012) — Historical perspective that helps temper hype: architectural wins usually follow hardware and tooling improvements.

I shipped my first iOS app, got rejected twice, and built a tool so it never happens again — Practical ops-level advice: App Store friction is real and worth automating checks for before release.


Until Next Time

If you’re planning a SwiftUI migration, gate risky screens behind a feature flag and add tests that assert cancellation and restoration behavior on device. Hit reply with a screen you’re worried about or forward this to a teammate who’s owning a rewrite — I read everything and will share what patterns have the best payoff.