iOS Dev Weekly — Issue #64
Opening
Everyone’s shipping custom SwiftUI controls, and a surprising number still fall apart under VoiceOver or Dynamic Type in real-world lists. At the same time, platform churn is real: tooling deprecations on macOS, and new compilation modes on the horizon. This week is about building UI that behaves correctly when the system pushes back.
This Week’s Big Story
Building VoiceOver-Friendly Custom SwiftUI Controls
When you merge visuals, gestures, and state into one custom view, you also inherit responsibility for how it’s narrated, focused, and interrupted. The hard part isn’t a label—it’s making the control act like one atomic element across rapid focus changes, scrolling, and async updates. If you’ve had QA call out “It looks right but sounds wrong,” this one earns a careful read.
Trend Signals
• hdiutil is deprecated in macOS 27 Golden Gate — if your CI or release tooling still shells out to it, start planning a migration path before it bites your pipeline. [Source: HackerNews]
• Embedded Swift Improvements Coming in Swift 6.4 — early signals suggest the subset is maturing, which could nudge more teams to share core logic between iOS and constrained targets. [Source: Swift.org Blog]
• Supporting Dynamic Type in iOS Apps — a timely reminder that auto layout isn’t enough; test with larger sizes and remember text scales can expose clipping and hidden assumptions. [Source: dev.to]
• I Was Tired of Watching ViewModels Turn Into Monsters — architecture churn continues, but the takeaway is consistent: constrain state and side effects or watch complexity compound. [Source: Medium]
• How We Built a Production-Ready Speech-to-Text Feature in Flutter — even outside Swift, the lesson echoes: production voice features live or die on error handling, buffering, and UX fallbacks. [Source: Medium]
Swift Snippet of the Week
import SwiftUI
struct VOCombinedControl: View {
@State private var isOn = false
@State private var count = 3
var body: some View {
Button {
isOn.toggle()
} label: {
HStack(spacing: 12) {
Image(systemName: isOn ? "star.fill" : "star")
.foregroundStyle(isOn ? .yellow : .primary)
Text("Favorites")
Spacer(minLength: 8)
Text("\(count)")
.monospacedDigit()
.padding(.horizontal, 8)
.padding(.vertical, 4)
.background(Capsule().fill(.secondary.opacity(0.2)))
Image(systemName: "chevron.right")
.font(.footnote)
.foregroundStyle(.secondary)
}
.padding(.vertical, 8)
// … (truncated for newsletter)
This pattern teaches a practical rule: compose multiple visual affordances into a single interactive element so you can control focus, announce state as one unit, and avoid VoiceOver treating each subview as a separate stop.
Community Picks
hdiutil is deprecated in macOS 27 Golden Gate — If your release process touches DMGs, read this now and adjust your build scripts before upgrades force your hand.
Supporting Dynamic Type in iOS Apps — Clear, pragmatic reminders that “works on Default” isn’t a pass; validate all content sizes.
I Was Tired of Watching ViewModels Turn Into Monsters — So I Built My Own iOS Architecture — You don’t need this exact framework, but the constraints it enforces are worth stealing.
Until Next Time
If your custom controls look great but stumble under a screen reader, you’re accumulating debt you’ll pay at the worst moment—start with this week’s piece and ship something your QA and users can trust. Hit reply with the nastiest VoiceOver bug you’ve fixed, or forward this to a teammate who owns your design system. I’ll be continuing the conversation on LinkedIn—jump in and share what patterns have made your controls robust.