iosswiftswift-concurrencyswift6

Swift 6 concurrency error of passing sending closure


I am getting this error in a couple of places in my code with Task closure after setting Swift 6 as Language version in XCode.

Passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure

Below is minimally reproducible sample code.

import Foundation

final class Recorder {
    
    var writer = Writer()
    
    func startRecording() {
        Task {
            await writer.startRecording()
            print("started recording")
        }
    }
    
    func stopRecording() {
        Task {
            await writer.stopRecording()
            print("stopped recording")
        }
    }
}

actor Writer {
    var isRecording = false
    
    func startRecording() {
        isRecording = true
    }
    
    func stopRecording() {
        isRecording = false
    }
}

Solution

  • Compiler's error is not bring too much information about the real error. Consider this line of code await writer.startRecording(), actually self is impiled so this code is actually await self.writer.startRecording().

    Now we can see the error occur because Recorder is not conform to Sendable so it can not be capture by closure of Task.

    You can solve your problem by make Recorder conform to Sendable.

    Another fix is to capture writer in Task closure because Actor is conform to Sendable by default.

    func startRecording() {
        Task { [weak writer] in
            await writer?.startRecording()
            print("started recording")
        }
    }