Irbisa · Шпаргалка
Строгая конкурентность Swift 6
Домены изоляции, Sendable, глобальные акторы, region isolation, sending, миграция на Swift 6
Что проверяет strict concurrency в Swift 6 и чем языковой режим отличается от версии компилятора?
// swift-tools-version: 6.0// Tools 6.0 = Swift 6 compiler; targets default to language mode 6.import PackageDescription let package = Package( name: "App",…Что такое домен изоляции в Swift и как значение может перейти из одного домена в другой?
Почему класс только с
let-свойствами всё равно неSendableи когда@unchecked Sendableбудет честным решением?import Foundationimport Synchronization // Rejected, one reason each:// class A: Sendable { let x = 1 } // not final// final class B: Sendable { var x = 1 } // mutable stored property…Swift 6 отклоняет оба объявления в
Services. О чём говорит каждая ошибка и какие формы допустимы для разделяемого изменяемого состояния?final class Analytics { var queue: [String] = []} enum Services { static var currentUserID: String? // (1) static let analytics = Analytics() // (2)}Что
nonisolated(unsafe)обещает компилятору и когда это честный ответ, а не способ заглушить ошибку?import Foundationimport Synchronization enum Metrics { private static let lock = NSLock() // Invariant: read and written only while `lock` is held.…Почему класс с
Mutexможет бытьSendableбез@uncheckedи какие уMutexограничения?import Synchronizationimport os // iOS 18+: the dictionary is reachable only through the lock.final class TokenCache: Sendable { private let tokens = Mutex<[String: String]>([:])…Найдите баг: этот
Sendable-класс статистики без ошибок компилируется в Swift 6, но под нагрузкой счётчики выходят меньше, чем было вызововrecord.final class RequestStats: Sendable { private let storage = Mutex<[String: Int]>([:]) var counts: [String: Int] { get { storage.withLock { $0 } } set { storage.withLock { $0 = newValue } } } func record(_ host: String) { counts[host, default: 0] += 1 } func reset() { counts = [:] }}Что такое глобальный актор и когда стоит объявлять свой вместо
@MainActorили обычногоactor?@globalActoractor StorageActor { static let shared = StorageActor()} @StorageActor…Что означает
nonisolatedна хранимом свойстве, на синхронном и наasync-методе и уводит ли он работу с актора?@MainActorfinal class Profile: Hashable { nonisolated let id: UUID // Sendable let: readable from any domain var name: String // main-actor state init(id: UUID, name: String) { self.id = id; self.name = name }…Скомпилируется ли этот код в языковом режиме Swift 6 и что изменится, если удалить строку с
print?final class Report { // not Sendable var title = ""} actor Archive { private var reports: [Report] = [] func store(_ r: Report) { reports.append(r) }} func archiveWeekly(_ archive: Archive) async { let report = Report() report.title = "Weekly" await archive.store(report) print(report.title)}Что может выразить параметр
sending, чего не может@Sendable, и почемуTask.initиaddTaskпринимаютsending-замыкания?final class Draft { var body = "" } // not Sendable actor Outbox { private var queued: [Draft] = [] func queue(_ d: Draft) { queued.append(d) }}…После включения Approachable Concurrency в таргете скролл подтормаживает, пока эта модель декодирует картинки. Почему и как исправить?
@MainActorfinal class GalleryModel { var thumbnails: [UIImage] = [] func load(_ files: [Data]) async { for data in files { if let image = await Self.decode(data) { thumbnails.append(image) } } } nonisolated static func decode(_ data: Data) async -> UIImage? { UIImage(data: data)?.preparingForDisplay() }}Как перевести большое приложение со Swift 5 на языковой режим Swift 6, не останавливая работу над фичами?
// Package.swift: one target at a time, leaves first.let package = Package( name: "App", targets: [ .target( name: "CoreModels",…Что меняют в таргете Approachable Concurrency и изоляция
MainActorпо умолчанию и почему их не стоит включать в общем фреймворке?Ваша
@MainActor-вью-модель должна конформитьEquatable, а компилятор отклоняет конформанс. Почему и какие есть варианты?@MainActorfinal class Model { let id: Int var rows: [String] = [] init(id: Int) { self.id = id }}…Что делает
@preconcurrencyна импорте и на конформансе протоколу и какой риск остаётся после того, как сборка позеленела?@preconcurrency import LegacyPlayer // stop diagnosing its missing Sendable @MainActorfinal class PlayerBox: NSObject { private let player = LegacyPlayer() private var finished = 0…Колбэк вендора по документации приходит в главном потоке, но метод
nonisolated. КогдаMainActor.assumeIsolatedуместен и когда он падает?@MainActorfinal class Player { private var progress: Double = 0 // SDK requirement is nonisolated; docs say "always called on the main thread". nonisolated func vendorDidTick(_ value: Double) {…Objective-C SDK вендора вызывает ваш делегат на произвольных потоках. Как встроить его в модуль Swift 6 без
@unchecked Sendableповсюду?final class ScannerBridge: NSObject, VendorScannerDelegate, Sendable { enum Event: Sendable { case found(String) } let events: AsyncStream<Event> private let continuation: AsyncStream<Event>.Continuation override init() { (events, continuation) = AsyncStream.makeStream(of: Event.self)…Таргет чисто компилируется в режиме Swift 6, но Thread Sanitizer находит гонку данных. Чего не видит компилятор и как найти гонку?