swift 如何过滤Actor对象?

xnifntxz  于 2023-01-25  发布在  Swift
关注(0)|答案(1)|浏览(110)

我有一个Actor对象,我希望它能够迭代和过滤。

actor DataModel {
    typealias Details = (passed: Bool, scores: [Int])
    private(set) var data: [Int: Details] = [:]

    func update(_ value: (Bool, [Int]), forKey key: Int) {
        data.updateValue(value, forKey: key)
    }

    subscript(id: Int) -> Details? {
        get {
            data[id]
        }

        set {
            data[id] = newValue
        }
    }

    func removeAll() {
        data.removeAll()
    }
}

extension DataModel: AsyncSequence, AsyncIteratorProtocol {
    typealias Element = (key: Int, value: Details)

    func next() async throws -> Element? {
        var iterator = data.makeIterator()
        return iterator.next()
    }

    nonisolated func makeAsyncIterator() -> Data {
        self
    }
}

let data = DataModel()
await data.update((false, [1, 2]), forKey: 0)

但是,每当我使用filter方法时,它就会进入无限循环。

let filtered = data.filter { el in
    /// infinite loop
    return el.value.passed || el.value.scores.count > 3
}

for try await i in filtered {
    print(i)
}
    • 更新**

创建了单独的迭代器,但出现以下错误:
不能从非隔离上下文引用参与者隔离属性"data

extension DataDetail: AsyncSequence {
    typealias Element = (key: Int, value: (passed: Bool, scores: [Int]))
    typealias AsyncIterator = DataInterator

    nonisolated func makeAsyncIterator() -> DataInterator {
        return DataInterator(data) /// Actor-isolated property 'data' can not be referenced from a non-isolated context
    }
}

struct DataInterator: AsyncIteratorProtocol {
    typealias Detail = (key: Int, value: (passed: Bool, scores: [Int]))

    private let details: [Int: (passed: Bool, scores: [Int])]
    lazy var iterator = details.makeIterator()
    
    init(_ details: [Int: (passed: Bool, scores: [Int])]) {
        self.details = details
    }
    
    mutating func next() async throws -> Detail? {
        let nextDetail = iterator.next()
        return nextDetail
    }
}
afdcj2ne

afdcj2ne1#

你的next()方法有一个错误,你在每次调用时都创建了一个新的迭代器,所以每次对next()方法的调用实际上都是一遍又一遍地返回data.first,它永远不会命中nil,所以它永远不会结束。
但是我不知道最简单的解决方法是什么,你不能从makeAsyncIterator()中直接得到return data.makeIterator(),因为data是角色隔离的。
您可能希望创建一个新的符合AsyncIteratorProtocol的结构体,该结构体 Package 您的actor并以actor隔离的方式出售其data的元素

相关问题