Section 10/161 menit

10. `nonisolated(unsafe)` dan `@preconcurrency`

10. nonisolated(unsafe) dan @preconcurrency

nonisolated(unsafe)

Digunakan saat Anda yakin sebuah property thread-safe tapi compiler tidak bisa memverifikasinya.

swift
// ❌ Tanpa nonisolated(unsafe): error karena stored property tidak bisa nonisolated biasa
@MainActor
class AppConfiguration {
    nonisolated let appName: String = "MyApp"  // ✓ — konstanta, boleh nonisolated

    // nonisolated var mutableSetting: String = "default"  // ❌ Error di Swift 6
}

// ✓ nonisolated(unsafe): untuk mutable state dengan jaminan manual
@MainActor
class LegacyCache {
    // Anda bertanggung jawab memastikan akses ke cache aman dari thread manapun
    nonisolated(unsafe) var cache: NSCache<NSString, AnyObject> = .init()
    // NSCache sudah thread-safe secara internal — aman dengan nonisolated(unsafe)
}

Kapan nonisolated(unsafe) Boleh Digunakan

swift
// 1. Object yang thread-safe secara internal
class SafeCounter {
    nonisolated(unsafe) private var _count: Int = 0
    nonisolated(unsafe) private let lock = NSLock()

    var count: Int {
        lock.withLock { _count }
    }

    func increment() {
        lock.withLock { _count += 1 }
    }
}

// 2. Singleton yang di-initialize sekali sebelum concurrency dimulai
class AppState {
    nonisolated(unsafe) static var configuration: AppConfiguration!

    static func setup() {
        // Dipanggil sebelum concurrent code berjalan
        configuration = AppConfiguration()
    }
}

// 3. Interop dengan C/Objective-C yang thread-safe tapi tidak terbukti ke Swift type system
class CoreFoundationWrapper {
    nonisolated(unsafe) let cfQueue: DispatchQueue = DispatchQueue(label: "com.app.cf")
}

@preconcurrency

Digunakan untuk adopsi bertahap — menekan warning dari tipe atau protocol yang belum di-update ke Swift Concurrency.

swift
// Suppress warning dari module lama yang belum annotate Sendable
@preconcurrency import OldFramework

// Jika protocol dari library lama tidak punya @Sendable
@preconcurrency protocol LegacyDelegate: AnyObject {
    func didComplete(result: LegacyResult)
}

// Conform dengan menekan warning untuk LegacyResult yang belum Sendable
class MyDelegate: @preconcurrency LegacyDelegate {
    func didComplete(result: LegacyResult) {
        // Compiler tidak warning meski LegacyResult belum Sendable
    }
}

@preconcurrency pada Type Declaration

swift
// Type dari SDK lama yang kita tahu aman tapi belum ada Sendable conformance
// Tambahkan di extension — jangan modif source aslinya
extension OldFrameworkObject: @unchecked Sendable {}

// Atau gunakan @preconcurrency untuk suppress warning sementara
@preconcurrency
class BridgeToLegacy {
    var legacyObject: OldFrameworkObject  // Tidak warning meski tidak Sendable
}