All Issues

iOS Dev Weekly — Issue #1

Opening

If your codebase still leans on Combine, you’re not wrong — but you should be deliberate about moving away. Async/await simplifies control flow, but it also changes timing, cancellation, and how backpressure shows up in real apps; treat migration as engineering, not magic.


This Week’s Big Story

Migrate Combine to Swift async/await

Replacing long Combine chains with async/await frequently makes code easier to read, but it also exposes subtle behavioral differences that can break production timing and cancellation assumptions. Migration is a series of design decisions — not a mechanical find-and-replace — where the tradeoffs between structured concurrency and Combine’s explicit demand matter. Read the guide if you want a pragmatic, testable roadmap that reduces release risk and keeps your team shipping.


Trend Signals

• Apple security design conversations are resurfacing, focusing on platform-level indicators and enclave boundaries — expect more public scrutiny around privacy UX and system guarantees. [Source: HackerNews]
• Community authors keep excavating SwiftUI’s lesser-known APIs, suggesting teams can gain tangible ergonomics and performance wins without a full rewrite. [Source: Medium]
• Discussion about Sendable and cross-thread value semantics is active again — this matters when you replace GCD patterns with structured concurrency. [Source: dev.to]


Swift Snippet of the Week

import SwiftUI
import Observation
import Foundation

// Simple Photo model matching a typical JSON response.
struct Photo: Identifiable, Codable, Hashable {
    let id: Int
    let title: String
    let thumbnailUrl: URL
}

// Network layer using async/await.
enum NetworkError: Error {
    case invalidURL, invalidResponse, decodingError(Error)
}

struct NetworkClient {
    static func fetchPhotos(matching query: String, limit: Int = 25) async throws -> [Photo] {
        guard var comps = URLComponents(string: "https://jsonplaceholder.typicode.com/photos") else {
            throw NetworkError.invalidURL
        }
        comps.queryItems = [URLQueryItem(name: "q", value: query), URLQueryItem(name: "_limit", value: "\(limit)")]
        guard let url = comps.url else { throw NetworkError.invalidURL }
        
        let (data, response) = try await URLSession.shared.data(from: url)
// ... (truncated for newsletter)

This pattern matters because it encodes a network-first migration path: replace publisher-based network calls with structured async code while keeping the rest of the system stable.


Community Picks

Apple Exclaves and the Secure Design of the Neo’s On-Screen Camera Indicator — A thoughtful look at platform-level security design that’s worth reading if you care about how system guarantees affect app UX. (https://daringfireball.net/2026/03/apple_enclaves_neo_camera_indicator)

SwiftUI Lesser-Known APIs That Can Improve Your Code — Part 3 — Practical suggestions here are the sort of low-risk improvements teams can adopt incrementally to get real wins. (https://medium.com/mobile-app-experts/swiftui-lesser-known-apis-that-can-improve-your-code-part-3-ad90fac224e6?source=rss——ios-5)


Until Next Time

If you’re planning a migration, start with an inventory, pick low-risk wins (networking first), and add async XCTest coverage before you ship. Hit reply with where migration hurt you — I’ll share patterns and the weird regressions teams actually hit, and we’ll compare notes over on LinkedIn.