Posts
iOS engineering insights — Swift, SwiftUI & Apple platform
Shortcuts that “do nothing” usually hide preventable failures: intent resolution misses, missing prompts, or long work killed silently — make them diagnosable, not mysterious
Shortcuts that “do nothing” usually hide preventable failures: intent resolution misses, missing prompts, or long work killed silently — make them diagnosable, not mysterious. Define AppIntent inputs with @Parameter and concrete type...
Memory growth during long sessions often points to an ownership leak, not a rendering bug — catch it with repeatable `Xcode Memory Graph` snapshots and diffs before assuming layout is the culprit
Memory growth during long sessions often points to an ownership leak, not a rendering bug — catch it with repeatable Xcode Memory Graph snapshots and diffs before assuming layout is the culprit. Capture a baseline snapshot, run a rep...
Parsing and type‑checking — not linking — is often what makes CI builds stall
Parsing and type‑checking — not linking — is often what makes CI builds stall. Stale or mismatched .swiftmodule files multiply that pain. Prebuild framework modules into explicit .swiftmodule and .swiftinterface artifacts in a dedica...
Header churn in incremental Xcode builds often shows up as repeated Objective‑C header parsing — missing `DEFINES_MODULE`, implicit umbrella headers, and inconsistent modules cache paths are common sources
Header churn in incremental Xcode builds often shows up as repeated Objective‑C header parsing — missing DEFINES_MODULE, implicit umbrella headers, and inconsistent modules cache paths are common sources. Enable per‑framework DEFINES...
Visual regressions at accessibility text sizes keep slipping into releases — clipped labels and truncated cells are often predictable and preventable
Visual regressions at accessibility text sizes keep slipping into releases — clipped labels and truncated cells are often predictable and preventable. Run automated Dynamic Type checks in CI so typography issues surface earlier. Add ...
Modifiers that capture mutable state can cause UI surprises under navigation and `List` reuse — treat them as small library contracts, not syntactic sugar
Modifiers that capture mutable state can cause UI surprises under navigation and List reuse — treat them as small library contracts, not syntactic sugar. Define ViewModifier types with explicit inputs, value semantics, and documented...
Ad‑hoc frame math sprinkled through view bodies breeds flaky, non‑deterministic layout
Ad‑hoc frame math sprinkled through view bodies breeds flaky, non‑deterministic layout. Pull spatial rules into focused Layout types to get deterministic sizing and easier tests. Centralize placement math behind a small Layout so you...
A tiny change to `body` or to state ownership can raise per-frame CPU on lower-end devices and turn a calm rollout into an urgent rollback
A tiny change to body or to state ownership can raise per-frame CPU on lower-end devices and turn a calm rollout into an urgent rollback. Profile on representative physical devices (include lower-end models) with Time Profiler, Core Ani...
Structured-concurrency migrations can change cancellation semantics in subtle ways — those differences often surface under load as leaked tasks, open sockets, or UI inconsistencies
Structured-concurrency migrations can change cancellation semantics in subtle ways — those differences often surface under load as leaked tasks, open sockets, or UI inconsistencies. Start small: wrap a critical callback with withChecked...
Converting globals to explicit DI often surfaces production-only failures: blank screens, duplicated network calls, or stale `ObservableObject` state that don't crash but lengthen incident time
Converting globals to explicit DI often surfaces production-only failures: blank screens, duplicated network calls, or stale ObservableObject state that don’t crash but lengthen incident time. Wire services at the @main App or per Scene...
Converting completion-handler telemetry to async/await can change cancellation and lifecycle semantics — and that can increase the risk of leaking data or leaving on-disk batches after consent changes
Converting completion-handler telemetry to async/await can change cancellation and lifecycle semantics — and that can increase the risk of leaking data or leaving on-disk batches after consent changes. Practical guardrails I use: Va...
If your codebase still uses URLSession completion handlers, moving to Swift async/await can simplify call sites — but it also changes how cancellation, error propagation, and observability are handled
If your codebase still uses URLSession completion handlers, moving to Swift async/await can simplify call sites — but it also changes how cancellation, error propagation, and observability are handled. Here’s a pragmatic, low-risk approa...
Stop treating migration from Combine to async/await as a mechanical find‑and‑replace — it’s a different execution model that affects timing, cancellation, and demand semantics
Stop treating migration from Combine to async/await as a mechanical find‑and‑replace — it’s a different execution model that affects timing, cancellation, and demand semantics. Practical roadmap I use with teams: Inventory and pick l...
A tangled web of push/pop calls and segues can slow teams down — but you can migrate to state‑driven navigation incrementally without a big rewrite
A tangled web of push/pop calls and segues can slow teams down — but you can migrate to state‑driven navigation incrementally without a big rewrite. Here’s a practical approach I’ve seen work in teams moving UIViewController navigation t...