TL;DR
I recently encountered a crash on SetNSColor(CGContext*, void const*)
with[__SwiftValue CGColor]: unrecognized selector sent to instance
. It took a while to find the root cause as the stack trace lacked a lot of detail. Ultimately it was a SwiftUI Color
in a UIKit API that expects a UIColor
(or raw CGColor
).
In this case I passed a SwiftUI Color
via the .foregroundColor
attribute of an NSAttributedString
that UIKit then rendered.
All fixed by feeding UIKit a the UIColor
, not the SwiftUI Color
.
Crash Log Deep Dive
Signature
SetNSColor(CGContext*, void const*)
-[__SwiftValue CGColor]: unrecognized selector sent to instance 0x123456789
SIGABRT: Terminating app due to uncaught exception 'NSInvalidArgumentException'
“SetNSColor” is rarely seen or at least noticed in iOS builds. 🤔
Digging shows that the symbol crops up when Core Graphics tries to resolve a colour that can’t answer CGColor
.
Why it Happens in UIKit
SwiftUI’s Color
is a value type with deferred resolution. This means you are passing around something small and lightweight that gets copied. You are not passing the actual underlying colour, more like something that tells you how to get the colour. For example it tells SwiftUI, “use the primary colour”, not “use this explicit RGB colour”. In the end, Color
will be resolved by the drawing system at the appropriate time.
This is fine when SwiftUI
is doing the drawing but if you pass that value beyond SwiftUI, e.g. NSAttributedString
— the framework boxes it in an internal __SwiftValue
. An object containing the Color
.
Later, UIKit needs a CGColor
, calls the selector on that object, but the SwiftUI drawing system isn’t invoked. UIKit finds nothing, and the runtime triggers unrecognized selector exception and crashes.
Our Culprit: .foregroundColor
on NSAttributedString
Repro in Three Lines
let attrs: [NSAttributedString.Key: Any] = [
.foregroundColor: Color.primary // ❌ SwiftUI colour inside UIKit
]
let boom = NSAttributedString(string: "Boom 💥", attributes: attrs)
label.attributedText = boom
Render the label and you’ll see the crash.
When the label is first drawn, UILabel
hands the attributed string to Core Text, which passes it down to Core Graphics. Core Graphics then asks each attribute object for a CGColor
. The boxed SwiftUI Color
can’t respond, so the runtime throws unrecognized selector and the app crashes.
A Minimal Fix
Swap in UIColor
(or provide a CGColor
directly):
let attrs: [NSAttributedString.Key: Any] = [
.foregroundColor: UIColor.label // ✅ concrete colour
]
label.attributedText = NSAttributedString(string: "All good 🚀", attributes: attrs)
Conclusion
Watch out for SwiftUI Color
sneaking into the wrong context. Keep UIKit fed with UIColor
. 😊