Francisco José García Navarro
Francisco José García Navarro
June 11, 2024

WWDC 2024: Everything an iOS Developer Needs to Know

WWDC 2024: Everything an iOS Developer Needs to Know
" The day-after technical summary — Swift 6, Apple Intelligence, Swift Testing and the biggest concurrency change since async/await "

I just finished watching the WWDC 2024 keynote and State of the Union, and I need to say it clearly: this is the most important WWDC since 2019, when Apple launched SwiftUI and Combine. And possibly more so.

Swift 6 arrives with compile-time data race safety. Apple Intelligence brings generative AI into the operating system. A new testing framework replaces the way we've written tests for a decade. And SwiftData finally supports custom backends.

But what strikes me most isn't the individual features — it's that Apple is closing an arc that started in 2020 with actors and async/await. Swift 6 is the culmination of that journey: safe concurrency by default, with no option to ignore it. And that's going to hurt in enterprise apps with millions of lines of code.

Swift 6: compile-time data race safety

This is the most important WWDC news for any iOS developer. Swift 6 language mode turns concurrency warnings into compilation errors. If your code has a potential data race, it doesn't compile. Full stop.

This extends the memory safety guarantees Swift already had (null safety, bounds checking) into the concurrency domain: actors, Sendable, isolation boundaries — everything is verified strictly.

The technical key that makes this viable is SE-0414: Region-based Isolation. The compiler performs flow analysis to prove when non-Sendable values can safely cross isolation boundaries. This drastically reduces the false positives that made strict concurrency checking impractical in Swift 5. This is complemented by the new sending keyword (SE-0430), which explicitly marks parameters and return values that cross isolation domains.

Most importantly for enterprise teams: migration is incremental. The Swift 6 compiler ships with Xcode 16 and compiles your existing code without changes. You opt into Swift 6 language mode per target, with SWIFT_LANGUAGE_MODE = 6 in build settings or .swiftLanguageMode(.v6) in Package.swift. Modules compiled in Swift 5 and Swift 6 coexist in the same binary.

// Swift 6: this no longer compiles if `MyModel` is not Sendable
func fetchData() async {
    let model = MyModel()
    Task.detached {
        model.process() // Error: capture of non-Sendable 'model'
    }
}

My recommendation: start with -strict-concurrency=complete in Swift 5 mode to see the warnings. Fix leaf targets first (utilities, networking, models), then work your way up. Don't try to migrate everything at once — I've seen codebases where enabling strict concurrency generates hundreds of errors. You need to go module by module.

Beyond concurrency, Swift 6 brings:

  • Typed throws (SE-0413): declare the error type with throws(ParseError). No more casting Error in every catch.
  • Noncopyable types in generics (SE-0427): Optional, Result and UnsafeBufferPointer accept ~Copyable types.
  • New Synchronization library: Atomic<Value> for lock-free operations and Mutex<Value> for synchronous mutual exclusion. Usable without async context.
  • Int128 / UInt128: native 128-bit integers.
  • count(where:): finally a direct method for counting elements that satisfy a condition.
  • Access-level imports: internal import, private import to control dependency visibility.

Apple Intelligence: AI comes to the operating system

Apple presents Apple Intelligence, their generative AI system that runs on-device on A17 Pro and M1+ chips, with a backend called Private Cloud Compute — Apple Silicon servers where data is never stored, never accessible to Apple, and whose software must be publicly logged for independent verification.

For developers, integration is largely automatic:

Writing Tools (rewrite, correct, summarise) appear in any standard UITextView or NSTextView without writing code. A new delegate API gives granular control (pausing sync while Writing Tools is active, for example).

Genmoji introduces NSAdaptiveImageGlyph, a new type for AI-generated emoji that renders inline in rich text.

But the deeper story is that App Intents becomes the bridge to Apple Intelligence. Apple has introduced 12 new App Intents domains — Books, Browsers, Camera, Mail, Photos, Presentations, Spreadsheets and more — covering more than 100 new actions that Siri's language models understand natively. You define assistant schemas describing your app's actions, and Apple Intelligence can invoke them via natural language.

Siri has a new visual design (glowing border instead of the sphere), screen awareness, cross-app actions, Type to Siri, and a ChatGPT fallback for questions that exceed its on-device capabilities.

For enterprise apps: if you haven't adopted App Intents yet, now is the time. It's the entry point to the entire system intelligence layer.

SwiftUI: MeshGradient, custom containers and zoom transitions

SwiftUI receives its most substantial update to date. Important change: App, Scene and View are now isolated to @MainActor by default, aligning with Swift 6's concurrency model.

MeshGradient is a new view that renders two-dimensional gradients defined by a grid of positions and colours. Fully animatable, perfect for dynamic backgrounds:

MeshGradient(
    width: 3, height: 3,
    points: [
        .init(0, 0), .init(0.5, 0), .init(1, 0),
        .init(0, 0.5), .init(0.5, 0.5), .init(1, 0.5),
        .init(0, 1), .init(0.5, 1), .init(1, 1)
    ],
    colors: [
        .red, .orange, .yellow,
        .green, .blue, .indigo,
        .purple, .pink, .white
    ]
)

The @Entry macro collapses the ~10 lines of EnvironmentKey boilerplate into a single line: @Entry var itemsPerPage: Int = 10. In a project with 20+ environment values, this is a significant cleanup.

The new custom container API (Group(subviewsOf:), ForEach(subviewOf:)) allows building container views with the same power as List or TabView, iterating over Subview and SubviewsCollection proxies. This is infrastructure that previously required hacks with _VariadicView.

Zoom transitions in navigation: .navigationTransition(.zoom(sourceID:in:)) with .matchedTransitionSource produces fluid hero animations in NavigationStack. The new Tab type and .tabViewStyle(.sidebarAdaptable) enable the iPadOS 18 floating tab bar that transforms into a sidebar.

ScrollView gains ScrollPosition to read exact offsets, onScrollGeometryChange to react to content changes, and onScrollVisibilityChange for visibility detection. @Previewable allows using @State directly in #Preview blocks.

Swift Testing: the successor to XCTest

Apple launches Swift Testing, a new open-source testing framework that redefines how we write tests. It's the biggest change in Apple testing since the introduction of XCTest.

import Testing

@Suite("Authentication")
struct AuthTests {
    @Test("Login with valid credentials")
    func loginSuccess() async throws {
        let result = try await AuthService.login(
            email: "test@example.com",
            password: "valid"
        )
        #expect(result.isAuthenticated)
        #expect(result.token != nil)
    }

    @Test("Login with invalid credentials",
          arguments: ["", "wrong", "expired"])
    func loginFailure(password: String) async throws {
        await #expect(throws: AuthError.self) {
            try await AuthService.login(
                email: "test@example.com",
                password: password
            )
        }
    }
}

Key differences from XCTest:

  • @Test marks any function as a test (no test prefix needed, no inheriting from XCTestCase).
  • #expect replaces all XCTAssert* variants with a single macro that captures source code and sub-values on failure.
  • #require stops the test early on failure (replaces XCTUnwrap).
  • Parameterised tests: the same function runs with multiple inputs, each as an independent case.
  • Traits: .tags(), .enabled(if:), .timeLimit(), .serialized to customise behaviour.
  • Parallel execution by default using Swift concurrency.

Swift Testing coexists with XCTest in the same target — you can migrate test by test. Current limitation: it doesn't support performance tests or UI tests (those still require XCTest).

My take: the ergonomics are vastly superior to XCTest. The #expect macro with expression capture is brilliant — on failure you see exactly what value each side of the comparison held, without needing custom messages. For new tests, there's no reason to keep using XCTest.

Xcode 16: on-device code completion and explicit modules

Predictive code completion is the headline feature: an ML model trained specifically for Swift and Apple SDKs, running entirely on-device on Apple Silicon. No cloud, no code sent anywhere. For enterprise teams with proprietary code, this is fundamental — you get intelligent autocomplete without compromising confidentiality.

The build system introduces Explicitly Built Modules, which splits compilation into three phases: dependency scanning, module compilation and source compilation. This improves parallelism, diagnostics and debugger speed (LLDB reuses compiled modules). Active by default for C/Objective-C, opt-in for Swift.

DWARF5 is the default debug symbol format, producing smaller dSYMs. New Flame Graph in Instruments to visualise execution time. The Thread Performance Checker now detects excessive disk writes and slow-launch diagnostics. And SPM package resolution no longer blocks the build.

SwiftData year 2: custom stores and change history

SwiftData addresses architectural gaps in its second year:

The DataStore protocol decouples SwiftData from the Core Data storage layer. You can implement custom persistence backends (JSON, SQLite variants, cloud storage) while keeping @Model, @Query and ModelContext working the same way. This completely changes SwiftData's value proposition: it's no longer just "Core Data with macros", it's an extensible persistence framework.

#Unique defines composite uniqueness constraints with automatic upsert. #Index creates simple or composite indexes for query performance. A new History API tracks model changes over time via transactions, changes and tokens — essential for server sync, widget updates, and handling out-of-process changes.

UIKit: UIUpdateLink, automatic trait tracking and unified animations

UIUpdateLink replaces CADisplayLink with automatic view tracking, low-latency mode for drawing apps, and better battery efficiency. Automatic trait tracking eliminates the need to manually call registerForTraitChanges — UIKit detects which traits you use in layoutSubviews, drawRect and updateConstraints, and automatically invalidates when they change.

Major interop news: SwiftUI's Animation types can now animate UIKit viewsUIView.animate(.spring) { ... } works directly. Gesture systems are unified with UIGestureRecognizerRepresentable, allowing UIKit gesture recognisers to participate in SwiftUI hierarchies.

New frameworks and notable APIs

  • Controls API: third-party widgets in the Control Centre, Lock Screen and Action button. Built on App Intents. App visibility outside the app.
  • AccessorySetupKit: simplifies Bluetooth/Wi-Fi pairing to a single tap, without broad network permissions.
  • Translation: programmatic access to Apple's translation models via TranslationSession.
  • Core ML: MLTensor for multidimensional operations, stateful models for LLMs, and 4-bit weight compression.
  • Vision framework: complete redesign with native Swift API and async/await.
  • visionOS 2: volume resizing, enterprise APIs, room and object tracking.
  • watchOS 11: automatic Live Activities on Apple Watch, expanded Double Tap API, interactive widgets.
  • macOS 15 Sequoia: iPhone Mirroring, Game Porting Toolkit 2.

Privacy: locked apps and automatic passkeys

iOS 18 introduces locked and hidden apps at the system level — users can lock any app with Face ID/Touch ID without any developer work. Limited contacts access shows a system picker to select specific contacts. And automatic passkey upgrades transparently transition password-based accounts to passkeys.

Conclusion: what to do now

WWDC 2024 closes one cycle and opens another. Swift 6 is the culmination of four years of work on safe concurrency. Apple Intelligence redefines the relationship between apps and the system. And Swift Testing modernises how we verify our code.

If I had to choose three concrete actions for an enterprise iOS team:

  1. Enable -strict-concurrency=complete in Swift 5 mode today. Start seeing the warnings, understand the patterns, and fix module by module. It's the biggest task and the most urgent.
  2. Implement App Intents in your main flows. With Apple Intelligence, App Intents goes from "nice to have" to being your app's entry point into the system.
  3. Use Swift Testing for all new tests. Don't migrate existing XCTest yet, but every test you write from now on should use @Test and #expect.

It's been a brutal WWDC. Swift 6, Apple Intelligence, Swift Testing — each of these changes individually would justify a full article. Together, they redefine what it means to develop for iOS. Time to roll up your sleeves.

Need help with migration?

💡 Do you have a project that needs migration? We can help you make the transition efficiently and without interrupting your development flow.

📩 Contact us here for more information.

Share:
About the author
Francisco José García Navarro

Francisco José García Navarro

Francisco José García Navarro is the co-founder and CEO of AtalayaSoft and an experienced iOS software engineer with over 25 years in software development. Specializing in native iOS applications, Francisco has a rich background working with high-profile clients such as Banco Santander, Fox International Channel, Repsol, and National Geographic.