Section 9/101 menit

9. Troubleshooting Error Umum

9. Troubleshooting Error Umum

Error 1: "Sending X risks causing data races"

swift
// ❌ Error di Swift 6, Warning di Swift 5 + StrictConcurrency
class SharedData {
    var value = 0
}

let data = SharedData()
Task { data.value += 1 }  // Error: non-Sendable type

// ✅ Solusi A: jadikan struct (jika value semantics cukup)
struct SharedData {
    var value = 0
}

// ✅ Solusi B: jadikan actor
actor SharedData {
    var value = 0
    func increment() { value += 1 }
}

// ✅ Solusi C: @unchecked Sendable (jika sudah thread-safe manual)
final class SharedData: @unchecked Sendable {
    private let lock = NSLock()
    private var _value = 0
    var value: Int {
        get { lock.withLock { _value } }
        set { lock.withLock { _value = newValue } }
    }
}

Error 2: "Main actor-isolated can not be referenced from nonisolated context"

swift
// ❌ Error: mengakses @MainActor property dari background
class ViewController: UIViewController {
    var label: UILabel = UILabel()
}

Task.detached {
    viewController.label.text = "hello"  // Error!
}

// ✅ Solusi A: tandai ViewController sebagai @MainActor
@MainActor
class ViewController: UIViewController {
    var label: UILabel = UILabel()
}

// ✅ Solusi B: gunakan MainActor.run untuk crossing boundary
Task.detached {
    await MainActor.run {
        viewController.label.text = "hello"
    }
}

// ✅ Solusi C: gunakan Task biasa (mewarisi @MainActor dari context)
// Jika sudah dalam @MainActor context:
Task {  // bukan Task.detached
    label.text = "hello"  // OK: Task mewarisi isolation
}

Error 3: "Protocol requires Sendable conformance"

swift
// ❌ Error: protocol yang butuh Sendable tapi conforming type bukan Sendable
protocol Service: Sendable {
    func execute() async
}

class MyService: Service {  // Error: class bukan Sendable
    func execute() async { }
}

// ✅ Solusi A: gunakan actor
actor MyService: Service {
    func execute() async { }
}

// ✅ Solusi B: jadikan final class + @unchecked Sendable
final class MyService: Service, @unchecked Sendable {
    private let lock = NSLock()
    func execute() async { }
}

// ✅ Solusi C: hapus Sendable dari protocol jika tidak diperlukan
protocol Service {
    func execute() async
}

Error 4: "Stored property cannot be declared @MainActor in non-isolated context"

swift
// ❌ Masalah: property @MainActor di struct yang tidak @MainActor
struct AppState {
    @MainActor var currentUser: User?  // Error di Swift 6
}

// ✅ Solusi A: jadikan seluruh struct @MainActor
@MainActor
struct AppState {
    var currentUser: User?
}

// ✅ Solusi B: pindahkan ke class/actor yang sudah @MainActor
@MainActor
class AppState: ObservableObject {
    @Published var currentUser: User?
}

Error 5: "any keyword required for existential"

swift
// ❌ Error di Swift 6 (warning di Swift 5 + ExistentialAny)
let service: MyProtocol = ConcreteService()  // harus pakai 'any'

// ✅ Solusi: tambahkan 'any' keyword
let service: any MyProtocol = ConcreteService()

// Untuk conditional compilation:
#if swift(>=6.0) || hasFeature(ExistentialAny)
let service: any MyProtocol = ConcreteService()
#else
let service: MyProtocol = ConcreteService()
#endif