iOS Dev Weekly — Issue #66
Opening
SwiftUI apps are getting bigger, and the pain shows up in all the usual places: previews that crash, features that toggle inconsistently across screens, and cells that re-render because a “global” leaked into view state. The fix isn’t another DI container; it’s making policy explicit and local. This week is about putting cross‑cutting decisions where SwiftUI already wants them: the environment.
This Week’s Big Story
Practical SwiftUI Environment Keys for Scalable Apps
Crashing previews, mis-scoped rollouts, and list churn often share one culprit: dependencies with no boundaries. Treat the SwiftUI environment as a typed, read-only policy layer and you get deterministic previews, safer feature flags, and fewer accidental re-renders. If you’ve ever threaded a logger or a clock through ten initializers, this is the click that buys your weekend back.
Trend Signals
• Embedded Swift Improvements Coming in Swift 6.4 — Apple is tightening the Embedded Swift subset, which signals real intent for Swift beyond iOS and opens doors for companion devices and on-device ML controllers. [Source: Swift.org Blog]
• Dropping BadUSB Keystrokes on macOS — Practical OS-level mitigations remind teams to threat-model peripherals and harden dev laptops, not just prod servers. [Source: dev.to]
• Why I Built a Budgeting App That Refuses to Connect to Your Bank — A push toward trust-by-design suggests more apps will trade integrations for explicit user control and simpler privacy postures. [Source: Medium]
• SwiftUI vs Jetpack Compose: Two Declarative Frameworks, Two Platform Philosophies — Useful comparative thinking if you’re sharing architecture across iOS/Android; the philosophical gaps explain why “just mirror it” often burns cycles. [Source: Medium]
Swift Snippet of the Week
import SwiftUI
enum Feature: Hashable { case newPaywall }
struct FeaturePolicy { let enabled: Set<Feature>; func isEnabled(_ f: Feature) -> Bool { enabled.contains(f) } }
private struct FeaturePolicyKey: EnvironmentKey { static let defaultValue = FeaturePolicy(enabled: []) }
extension EnvironmentValues { var featurePolicy: FeaturePolicy { get { self[FeaturePolicyKey.self] } set { self[FeaturePolicyKey.self] = newValue } } }
struct PaywallView: View {
@Environment(\.featurePolicy) private var policy
var body: some View {
Text(policy.isEnabled(.newPaywall) ? "New Paywall" : "Legacy Paywall")
}
}
struct CohortGate: View {
let cohort: String
var body: some View {
let policy = FeaturePolicy(enabled: cohort == "A" ? [.newPaywall] : [])
return PaywallView().environment(\.featurePolicy, policy)
}
}
// … (truncated for newsletter)
This pattern decouples feature decisions from view construction, so you can swap policies at the composition root for cohorts, previews, and tests without leaking state or inflating initializers.
Community Picks
Dropping BadUSB Keystrokes on macOS Before They Open Spotlight — A hands-on reminder to harden macOS workstations against “it’s just a cable” attacks.
Why I Built a Budgeting App That Refuses to Connect to Your Bank — A compelling case for local-first finance UX and fewer brittle integrations.
Swift’s Tokenised Deposit Ledger Is Not a Swift Coin — and That Is the Point — Not about the language; useful context for fintech teams navigating bank rails vs. crypto narratives.
Until Next Time
If your SwiftUI app is feeling “global,” the environment keys article is the smallest change with the biggest stability payoff—go read it and try one policy this week. Then hit reply or join the LinkedIn thread to share how you scope flags, clocks, and loggers without tripping re-renders. Forward this to a teammate who’s been untangling initializer soup.