首页 > 解决方案 > 使参与者符合序列协议

问题描述

如何使参与者符合Sequence协议?以下代码生成编译器警告:

与全局角色“MainActor”隔离的实例方法“makeIterator()”无法满足协议“序列”的相应要求

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

标签: swiftconcurrencyswift-concurrency

解决方案


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

这意味着您的示例等效于:

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

这是一个问题,因为Sequence有一个makeIterator不孤立于特定全局参与者的要求。如果是这种情况,您将无法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
    }
}

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

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


推荐阅读