Consider the code below. It uses the AppKit (macOS) MPMediaItemArtwork
function to set the artwork in MPNowPlayingInfoCenter
.
During runtime, when compiled with Swift 6
, this gives the warning:
warning: data race detected: @MainActor function at MPMediaItemArtwork/ContentView.swift:22 was not called on the main thread
It seems that the requestHandler
is not called on the main thread. Adding @MainActor in
doesn't seem to make any difference. I may be a little rusty on the Objective-C side, but I can't figure out how to return the image on the main thread as it won't let me use a Task
with a return value, as it doesn't support concurrency.
import SwiftUI
import MediaPlayer
struct ContentView: View {
var body: some View {
Text("Test")
.padding()
.task {
await MainActor.run {
let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default()
var nowPlayingInfo = [String: Any]()
let image = NSImage(named: "image")!
// warning: data race detected: @MainActor function at MPMediaItemArtwork/ContentView.swift:22 was not called on the main thread
nowPlayingInfo[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(boundsSize: image.size, requestHandler: { _ in
// Not on main thread here!
return image
})
nowPlayingInfoCenter.nowPlayingInfo = nowPlayingInfo
}
}
}
}
Here is a version I have updated to use async/await
, however it still gives the same error on the same line:
extension MPMediaItemArtwork: @unchecked Swift.Sendable {
@MainActor
static func with(image: NSImage) async -> MPMediaItemArtwork {
await withCheckedContinuation { [image] continuation in
continuation.resume(returning: MPMediaItemArtwork(boundsSize: image.size) { [image] _ in
return image
})
}
}
}
.task {
nowPlayingInfo[MPMediaItemPropertyArtwork] = await MPMediaItemArtwork.with(image: image)
}
It turns out there is an easy fix here. Simply marking the completion handler as @Sendable
.
let artwork = MPMediaItemArtwork(boundsSize: image.size, requestHandler: { @Sendable _ in
return image
})
I'm still confused as to why there was no compiler warning or error here, but hopefully that's something Apple can/will fix.