使 Actor 符合 Sequence 协议

Phi*_*den 3 concurrency swift swift-concurrency

如何让参与者遵守协议Sequence?以下代码生成编译器警告:

与全局参与者“MainActor”隔离的实例方法“makeIterator()”无法满足协议“Sequence”的相应要求

@MainActor class Test: Sequence {
    private var contents: [Int] = []
    
    func makeIterator() -> Array<Int>.Iterator {
        contents.makeIterator()
    }
}
Run Code Online (Sandbox Code Playgroud)

Fil*_*kel 6

将全局参与者(例如@MainActor)应用于类型声明会@MainActor在该类型的属性和方法中添加隐式。

这意味着您的示例相当于:

class Test: Sequence {
    @MainActor private var contents: [Int] = []
    
    @MainActor 
    func makeIterator() -> Array<Int>.Iterator {
        contents.makeIterator()
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个问题,因为SequencemakeIterator要求并非孤立于特定的全球参与者。如果是这种情况,您将无法在Array后台线程中使用 for 循环。因此,要选择退出隐式隔离,您可以编写:

@MainActor class Test: Sequence {
    private var contents: [Int] = []
    
    nonisolated func makeIterator() -> Array<Int>.Iterator {
        // You can't use the isolated property 'contents'
        // here, because it's isolated
    }
}
Run Code Online (Sandbox Code Playgroud)

也许您打算遵守Test类似Sequence的协议,其要求与@MainActor. 不幸的是,类似的功能仅被提议作为未来的方向。

如果您仍然感到困惑,那么值得退一步思考一下您真正想要实现的目标。Actor 隔离提供了一种安全地改变跨线程共享数据的方法。因此,没有隔离意味着缺乏突变(因此能够标记let属性nonisolated)或除参与者之外的同步机制。