axiom-assume-isolated
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseassumeIsolated — Synchronous Actor Access
assumeIsolated — 同步访问Actor
Synchronously access actor-isolated state when you know you're already on the correct isolation domain.
当你确定当前处于正确的隔离域时,可同步访问Actor隔离状态。
When to Use
使用场景
✅ Use when:
- Testing MainActor code synchronously (avoiding Task overhead)
- Legacy delegate callbacks documented to run on main thread
- Performance-critical code avoiding async hop overhead
- Protocol conformances where callbacks are guaranteed on specific actor
❌ Don't use when:
- Uncertain about current isolation (use instead)
await - Already in async context (you have isolation)
- Cross-actor calls needed (use async)
- Callback origin is unknown or untrusted
✅ 适用场景:
- 同步测试MainActor代码(避免Task带来的开销)
- 文档明确说明运行在主线程的旧版代理回调
- 对性能要求高、需避免异步跳转开销的代码
- 回调被保证在特定Actor上执行的协议一致性实现
❌ 不适用场景:
- 不确定当前隔离域时(改用)
await - 已处于异步上下文(已有隔离保障)
- 需要跨Actor调用时(使用异步方式)
- 回调来源未知或不可信时
API Reference
API 参考
MainActor.assumeIsolated
MainActor.assumeIsolated
swift
static func assumeIsolated<T>(
_ operation: @MainActor () throws -> T,
file: StaticString = #fileID,
line: UInt = #line
) rethrows -> T where T: SendableBehavior: Executes synchronously. Crashes if not on MainActor's serial executor.
swift
static func assumeIsolated<T>(
_ operation: @MainActor () throws -> T,
file: StaticString = #fileID,
line: UInt = #line
) rethrows -> T where T: Sendable行为:同步执行。若当前不在MainActor的串行执行器上,会崩溃。
Custom Actor assumeIsolated
自定义Actor的assumeIsolated
swift
func assumeIsolated<T>(
_ operation: (isolated Self) throws -> T,
file: StaticString = #fileID,
line: UInt = #line
) rethrows -> T where T: Sendableswift
func assumeIsolated<T>(
_ operation: (isolated Self) throws -> T,
file: StaticString = #fileID,
line: UInt = #line
) rethrows -> T where T: SendableTask vs assumeIsolated
Task vs assumeIsolated
| Aspect | | |
|---|---|---|
| Timing | Deferred (next run loop) | Synchronous (inline) |
| Async support | Yes (can await) | No (sync only) |
| Context | From any context | Must be sync function |
| Failure mode | Runs anyway | Crashes if wrong isolation |
| Use case | Start async work | Verify + access isolated state |
| 维度 | | |
|---|---|---|
| 执行时机 | 延迟执行(下一个运行循环) | 同步执行(内联) |
| 异步支持 | 是(可使用await) | 否(仅支持同步) |
| 使用上下文 | 任意上下文 | 必须在同步函数中 |
| 失败模式 | 仍会执行 | 若隔离域错误则崩溃 |
| 适用场景 | 启动异步任务 | 验证并访问隔离状态 |
Patterns
实践模式
Pattern 1: Testing MainActor Code
模式1:测试MainActor代码
swift
@Test func viewModelUpdates() {
MainActor.assumeIsolated {
let vm = ViewModel()
vm.update()
#expect(vm.state == .updated)
}
}swift
@Test func viewModelUpdates() {
MainActor.assumeIsolated {
let vm = ViewModel()
vm.update()
#expect(vm.state == .updated)
}
}Pattern 2: Legacy Delegate Callbacks
模式2:旧版代理回调
From WWDC 2024-10169 — When documentation guarantees main thread delivery:
swift
@MainActor
class LocationDelegate: NSObject, CLLocationManagerDelegate {
var location: CLLocation?
// CLLocationManager created on main thread delivers callbacks on main thread
nonisolated func locationManager(
_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]
) {
MainActor.assumeIsolated {
self.location = locations.last
}
}
}来自WWDC 2024-10169 — 当文档保证回调在主线程执行时:
swift
@MainActor
class LocationDelegate: NSObject, CLLocationManagerDelegate {
var location: CLLocation?
// 在主线程创建的CLLocationManager会在主线程触发回调
nonisolated func locationManager(
_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]
) {
MainActor.assumeIsolated {
self.location = locations.last
}
}
}Pattern 3: @preconcurrency Shorthand
模式3:@preconcurrency 简写
@preconcurrencyassumeIsolatedswift
// ❌ Manual approach (verbose)
extension MyClass: SomeDelegate {
nonisolated func callback() {
MainActor.assumeIsolated {
self.updateUI()
}
}
}
// ✅ Using @preconcurrency (equivalent, cleaner)
extension MyClass: @preconcurrency SomeDelegate {
func callback() {
self.updateUI() // Compiler wraps in assumeIsolated
}
}When protocol adds isolation: becomes unnecessary and compiler warns.
@preconcurrency@preconcurrencyassumeIsolatedswift
// ❌ 手动方式(繁琐)
extension MyClass: SomeDelegate {
nonisolated func callback() {
MainActor.assumeIsolated {
self.updateUI()
}
}
}
// ✅ 使用@preconcurrency(等效且更简洁)
extension MyClass: @preconcurrency SomeDelegate {
func callback() {
self.updateUI() // 编译器会自动包装为assumeIsolated
}
}当协议添加隔离约束时:将不再必要,编译器会发出警告。
@preconcurrencyPattern 4: Thread Check Before assumeIsolated
模式4:assumeIsolated前的线程检查
When caller context is unknown (e.g., library code):
swift
func getView() -> UIView {
if Thread.isMainThread {
return createHostingViewOnMain()
} else {
return DispatchQueue.main.sync {
createHostingViewOnMain()
}
}
}
private func createHostingViewOnMain() -> UIView {
MainActor.assumeIsolated {
let hosting = UIHostingController(rootView: MyView())
return hosting.view
}
}当调用者上下文未知时(例如库代码):
swift
func getView() -> UIView {
if Thread.isMainThread {
return createHostingViewOnMain()
} else {
return DispatchQueue.main.sync {
createHostingViewOnMain()
}
}
}
private func createHostingViewOnMain() -> UIView {
MainActor.assumeIsolated {
let hosting = UIHostingController(rootView: MyView())
return hosting.view
}
}Pattern 5: Custom Actor Access
模式5:自定义Actor访问
swift
actor DataStore {
var cache: [String: Data] = [:]
nonisolated func synchronousRead(key: String) -> Data? {
// Only safe if called from DataStore's executor
assumeIsolated { isolated in
isolated.cache[key]
}
}
}swift
actor DataStore {
var cache: [String: Data] = [:]
nonisolated func synchronousRead(key: String) -> Data? {
// 仅当从DataStore的执行器调用时才安全
assumeIsolated { isolated in
isolated.cache[key]
}
}
}Common Mistakes
常见错误
Mistake 1: Silencing Compiler Errors
错误1:用assumeIsolated屏蔽编译器错误
swift
// ❌ DANGEROUS: Using assumeIsolated to silence warnings
func unknownContext() {
MainActor.assumeIsolated {
updateUI() // Crashes if not actually on main actor!
}
}
// ✅ When uncertain, use proper async
func unknownContext() async {
await MainActor.run {
updateUI()
}
}swift
// ❌ 危险:使用assumeIsolated消除警告
func unknownContext() {
MainActor.assumeIsolated {
updateUI() // 如果实际不在MainActor上,会崩溃!
}
}
// ✅ 不确定上下文时,使用标准异步方式
func unknownContext() async {
await MainActor.run {
updateUI()
}
}Mistake 2: Assuming GCD Main Queue == MainActor
错误2:假设GCD主队列 == MainActor
They're usually the same, but not guaranteed. Check documentation or use async.
两者通常是相同的,但不保证绝对一致。请查阅文档或使用异步方式。
Mistake 3: Using in Async Context
错误3:在异步上下文中使用
swift
// ❌ Unnecessary — you already have isolation
@MainActor
func updateState() async {
MainActor.assumeIsolated { // Pointless
self.state = .ready
}
}
// ✅ Direct access
@MainActor
func updateState() async {
self.state = .ready
}swift
// ❌ 不必要 — 你已处于隔离域中
@MainActor
func updateState() async {
MainActor.assumeIsolated { // 毫无意义
self.state = .ready
}
}
// ✅ 直接访问
@MainActor
func updateState() async {
self.state = .ready
}When @preconcurrency Becomes Unnecessary
何时@preconcurrency不再必要
If the protocol later adds MainActor isolation:
swift
// Library update:
@MainActor
protocol CaffeineThresholdDelegate: AnyObject {
func caffeineLevel(at level: Double)
}
// Your code — @preconcurrency now warns:
// "@preconcurrency attribute on conformance has no effect"
extension Recaffeinater: CaffeineThresholdDelegate {
func caffeineLevel(at level: Double) {
// Direct access, no wrapper needed
}
}如果协议后续添加了MainActor隔离约束:
swift
// 库更新:
@MainActor
protocol CaffeineThresholdDelegate: AnyObject {
func caffeineLevel(at level: Double)
}
// 你的代码 — @preconcurrency现在会触发警告:
// "@preconcurrency属性在一致性实现中无效"
extension Recaffeinater: CaffeineThresholdDelegate {
func caffeineLevel(at level: Double) {
// 直接访问,无需包装
}
}Crash Behavior
崩溃行为
Per Apple documentation:
"If the current context is not running on the actor's serial executor... this method will crash with a fatal error."
Trapping is intentional: Better to crash than corrupt user data with a race condition.
根据Apple文档:
"如果当前上下文未在Actor的串行执行器上运行...该方法会触发致命错误导致崩溃。"
主动触发崩溃是有意设计的:比起因竞态条件损坏用户数据,崩溃是更安全的选择。
Resources
参考资源
WWDC: 2024-10169
Docs: /swift/mainactor/assumeisolated, /swift/actor/assumeisolated
Skills: axiom-swift-concurrency
WWDC: 2024-10169
文档: /swift/mainactor/assumeisolated, /swift/actor/assumeisolated
技能: axiom-swift-concurrency