Issue #989
In Swift 6, Apple introduced stricter rules to help make your code safer when using concurrency (like async, await, Task, and actor). These rules check that types used in concurrent code are safe to share across threads.
Types that are safe to use across threads are called Sendable.
But here’s the catch: NSImage is not Sendable by default. That means if you try to use an NSImage inside a Task or actor, Swift will show a warning or error.
Use unchecked
If you’re sure that you’re using the image safely (e.g., you only read from it, or you handle all thread access carefully), you can force Swift to treat it as Sendable:
extension NSImage: @unchecked @retroactive Sendable {}
Use alternative Sendable friendly type
If you want to pass an image between tasks safely, convert it into something that is Sendable:
if let tiffData = image.tiffRepresentation,
let bitmap = NSBitmapImageRep(data: tiffData),
let pngData = bitmap.representation(using: .png, properties: [:]) {
// pngData is Sendable ✅
}
CGImage
is also a thread-safe image format you can use:
if let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) {
// cgImage is Sendable ✅
}
Use an actor to Protect the Image
If you want to store and use NSImage safely, you can wrap it in an actor. An actor keeps everything thread-safe:
actor ImageStore {
private var image: NSImage?
func set(_ newImage: NSImage) {
image = newImage
}
func get() -> NSImage? {
return image
}
}
Start the conversation