Section 9/131 menit

9. Migration Guide Swift 5 → Swift 6

9. Migration Guide Swift 5 → Swift 6

Langkah 1: Aktifkan Warning Dulu

Di Xcode, set SWIFT_STRICT_CONCURRENCY = targeted terlebih dahulu untuk melihat warning sebelum Swift 6 mode penuh:

swift
// Package.swift
.target(
    name: "MyTarget",
    swiftSettings: [
        .enableExperimentalFeature("StrictConcurrency")
    ]
)

Langkah 2: Pola Umum dan Solusinya

Pattern 1: Class yang diakses dari banyak thread

swift
// BEFORE (Swift 5)
class AppSettings {
    var isDarkMode: Bool = false
    var language: String = "en"
}

// AFTER (Swift 6) — opsi A: jadikan actor
actor AppSettings {
    var isDarkMode: Bool = false
    var language: String = "en"
}

// AFTER (Swift 6) — opsi B: isolasi ke @MainActor jika hanya untuk UI
@MainActor
class AppSettings {
    var isDarkMode: Bool = false
    var language: String = "en"
}

Pattern 2: Completion handler ke async/await

swift
// BEFORE
func fetchUser(id: String, completion: @escaping (User?) -> Void) {
    URLSession.shared.dataTask(with: request) { data, _, _ in
        completion(parse(data))
    }.resume()
}

// AFTER (Swift 6) — async + Sendable
func fetchUser(id: String) async -> User? {
    let (data, _) = try? await URLSession.shared.data(for: request)
    return parse(data)
}

Pattern 3: Notification observer

swift
// BEFORE
NotificationCenter.default.addObserver(
    forName: .someNotification,
    object: nil,
    queue: .main
) { notification in
    self.handleNotification(notification)
}

// AFTER (Swift 6)
Task { @MainActor in
    for await notification in NotificationCenter.default.notifications(named: .someNotification) {
        handleNotification(notification)
    }
}

Pattern 4: DispatchQueue → Actor

swift
// BEFORE
let queue = DispatchQueue(label: "com.app.data", attributes: .concurrent)
var dataStore: [String: Any] = [:]

func set(_ value: Any, for key: String) {
    queue.async(flags: .barrier) { self.dataStore[key] = value }
}

// AFTER (Swift 6)
actor DataStore {
    private var store: [String: Any] = [:]
    
    func set(_ value: Any, for key: String) {
        store[key] = value
    }
}

Langkah 3: Urutan Prioritas Migrasi

  1. Model/Data layer — jadikan actor atau Sendable struct
  2. Service layer — jadikan actor atau global actor
  3. ViewModel — anotasi @MainActor
  4. View/ViewController — anotasi @MainActor
  5. Utility/Helper — nonisolated jika memungkinkan, atau sesuaikan