Search code examples
swiftconcurrencyswift-concurrency

How to access an actor from within a filter closure


I'm having trouble working out how to access an actor from a filter closure. Take this example code:

import Foundation

actor MyActor {
    var contents: [String]
    
    init() {
        self.contents = []
    }
}


let myActor = MyActor()
let list: [String] = []

Task {
    list.filter { item in myActor.contents.contains { $0 == item } }
}

I get the syntax error: Actor-isolated property 'contents' can not be referenced from a non-isolated context. Which makes sense, but I just cannot work out how to provide the correct syntax.


Solution

  • Put the actor's contents in a local let constant first, then use that local constant in filter:

    Task {
        let actorContents = await myActor.contents
        let result = list.filter { item in actorContents.contains { $0 == item } }
    }
    

    You wouldn't want filter to use the updated myActor.contents halfway through, if myActor.contents changes at some point during the filtering, right? Therefore, make a local copy of it first, and use that.

    Also, consider using a Set for better efficiency:

    let actorContents = Set(await myActor.contents)
    let result = list.filter { item in actorContents.contains(item) }