Swift Evolution Monthly: May-November 2024

Discover the latest Swift updates, from Objective-C compatibility improvements to metatype keypaths, trailing commas, and new compiler controls—plus a must-have app for tracking proposals!

Swift Evolution Monthly: May-November 2024
Photo by Nubelson Fernandes / Unsplash

Swift’s GitHub repositories have officially moved from the Apple organization to the new swiftlang organization during the summer, signaling a significant step in Swift’s evolution as a community-driven language. Meanwhile, Swift 6 brought major advances in concurrency and data-race safety. But since those changes are already well-documented in other places, I will skip the concurrency topic and focus on other improvements to Swift that are around the corner.

Looking ahead, Swift’s evolution isn’t just about concurrency. Ongoing efforts, such as the proposed Vision document for Strictly-Safe Swift, are expanding the language’s capabilities beyond app development, particularly in embedded systems or system-level programming. That said, this newsletter remains grounded in what matters most to app developers. So let's dive in!

Accepted Proposal Summaries

SE-0436: Objective-C implementations in Swift

Links: 📝 Proposal  | 💬 Review  | ✅ Acceptance

A new syntax allows implementing Objective-C headers in Swift while maintaining full backward compatibility. This is particularly valuable when modernizing existing iOS apps with Swift while keeping Objective-C compatibility:

// MyView.h
@interface MyView : UIView
@property (nonatomic) CGFloat cornerRadius;
- (void)animate;
@end
// MyView.swift
@objc @implementation extension MyView {
    var cornerRadius: CGFloat = 0 {
        didSet { layer.cornerRadius = cornerRadius }
    }
    
    func animate() {
        // Swift implementation that's fully compatible with Objective-C
    }
}

This bridges the gap between modern Swift development and legacy Objective-C code, making gradual migration easier. While most relevant for teams maintaining Objective-C codebases, it's useful for any iOS developer working with mixed codebases or third-party Objective-C frameworks. And certainly Apple system engineers modernizing old system frameworks using Swift.

SE-0438: Metatype Keypaths

Links: 📝 Proposal  | 💬 Review  | ✅ Acceptance

This proposal allows keypath expressions to access static properties in Swift, introducing metatype keypaths using the .Type syntax.

Here's a practical example of how it simplifies code, especially when working with databases or property wrappers:

struct User {
    static let tableName = "users"
    static let primaryKey = "id"
}

// Before: Required workarounds or verbose syntax
let table = database.table(named: User.tableName)

// After: Can use keypaths directly
let tableKeyPath = \User.Type.tableName
let table = database[keyPath: tableKeyPath]

This is a moderate improvement that will be particularly valuable for developers working with frameworks that use keypaths extensively (like SwiftData or other database layers) and those building property wrapper-based systems. While not revolutionary, it removes an annoying limitation that required developers to create workarounds for accessing static properties through keypaths.

Now, we're just missing Enum Case Keypaths – I hope we get them soon!

SE-0439: Allow trailing comma in comma-separated lists

Links: 📝 Proposal  | 💬 Review  | ✅ Acceptance

This proposal extends Swift's existing trailing comma support (currently limited to arrays and dictionaries) to all comma-separated lists that have clear terminators, like function parameters, tuples, and conditional statements.

Here's a practical example showing how it improves code maintenance, especially with version control:

func fetchUser(
    id: String,
    includeDetails: Bool = true,
    cachePolicy: CachePolicy = .default, // Adding/removing parameters is now cleaner
) {
    // ...
}

let coordinates = (
    latitude: 37.7749,
    longitude: -122.4194,
) // Better diffs when modifying values

This is a small but meaningful quality-of-life improvement that will be particularly appreciated by developers working on large codebases where code formatting and version control cleanliness are important. It reduces noise in git diffs and makes code reorganization smoother. Nice to see these kinds of improvements!

SE-0443: Precise Control Flags over Compiler Warnings

Links: 📝 Proposal  | 💬 Review  | ✅ Acceptance

Swift adds granular control over compiler warnings, allowing developers to selectively upgrade warnings to errors or keep certain warnings as warnings. This is particularly valuable when maintaining large codebases:

// See which group a warning belongs to
swiftc -print-diagnostic-groups MyApp.swift

// Treat all warnings as errors except deprecations
swiftc -warnings-as-errors -Wwarning deprecated MyApp.swift

// Only make API availability warnings into errors
swiftc -Werror availability MyApp.swift

This feature helps teams maintain strict code quality while being pragmatic about certain warning categories. For example, you can enforce strict handling of memory management warnings while allowing time to address deprecation warnings during major version upgrades. It's especially useful when upgrading to new Swift versions or SDK releases that introduce new deprecations.

🌐
Wanna grow your app? Check out TranslateKit!
A drag & drop translator for String Catalog files – it's really easy.
Get it now to machine-translate your app to up to 150 languages!

SE-0444: Member import visibility

Links: 📝 Proposal  | 💬 Review  | ✅ Acceptance

Did you ever notice that you could access extensions from third-party Swift packages you didn't even import in a given Swift file? While you always needed to import a module to use its types, extensions on existing types like String were silently available through transitive imports. Here's why that's problematic:

// Without importing GroceryKit, its extensions are still available
import RecipeKit
let recipe = "ingredients...".parse() // Ambiguous if GroceryKit adds parse()!

// The fix: Extensions need explicit imports
import RecipeKit
let recipe = "ingredients...".parse() // Unambiguous - only sees RecipeKit's parse()

This proposal fixes this inconsistency in Swift's module system by making extension methods follow the same visibility rules as types. Due to the breaking change nature (you may need a lot more imports), it will initially be available behind the MemberImportVisibility compiler flag before becoming the default behavior in a future Swift version.

SE-0445: Improving String.Index's printed descriptions

Links: 📝 Proposal  | 💬 Review  | ✅ Acceptance

A quality-of-life improvement coming in Swift 6.1 that makes debugging string operations easier by giving String.Index values more meaningful descriptions:

let text = "👋🏼 Hello"

// Before: Cryptic output
print(text.firstRange(of: "el")!)  
// Index(_rawBits: 655623)..<Index(_rawBits: 852487)

// After: Clear position information  
print(text.firstRange(of: "el")!)
// 6[utf8]..<8[utf8]

This is a small but useful enhancement that will particularly benefit developers working on text processing code or debugging string-related issues.

Other Accepted Proposals

✉️
Don't want to miss future issues? Subscribe to the newsletter.

Proposals in Progress

Noteworthy Active Threads

Other News

Before wrapping up, I want to highlight Proposal Monitor by Victor Martins—a perfect companion for anyone wanting to dive deeper into Swift Evolution. While this newsletter keeps you informed about key developments, Proposal Monitor is ideal if you want to track every proposal, stay up-to-date with push notifications, or give timely feedback during review periods. Available on iOS, iPadOS, and visionOS, it’s a fantastic tool for following Swift’s evolution more closely. 🚀

🤙
Enjoyed this article? Get my expert advice!
No matter if you're stuck with a problem or just want feedback for your code or app idea. Book a session with me and I'll help you!
👨‍💻
Want to Connect?
Follow me on 🦋 Bluesky, 🐦 Twitter (X), and 🦣 Mastodon.