iosnsattributedstringuigraphicsimagerenderer

[__NSCFType set]: unrecognized selector with NSAttributedString:draw() gets called, based on width of position


If the code below is run it causes an exception

'NSInvalidArgumentException', reason: '-[__NSCFType set]: unrecognized selector sent to instance 0x283130be0'

However, the exception can be removed by reducing the width value from 100.0 in positionRect, for example setting it to something like 50.0 removes the exception.

But why is this? With a width value of 100.0 specified for positionRect, that's well short of the width of imageSize. And even if there is some size issue, why is there an unrecognized selector exception?

let imageSize = CGSize(width: 400, height: 100)
let testRenderer = UIGraphicsImageRenderer(size: imageSize)
let testImage = testRenderer.image { context in
    context.cgContext.setFillColor(UIColor.black.cgColor)
    context.fill(CGRect(origin: .zero, size: imageSize))
    
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.alignment = .left
    let attributes: [NSAttributedString.Key: Any] = [
        .font: UIFont.systemFont(ofSize: 8.0),
        .paragraphStyle: paragraphStyle,
        .foregroundColor: UIColor.white.cgColor
    ]
    
    let attributedString = NSAttributedString(string: "This is some text", attributes: attributes)
    let positionRect = CGRect(x: 10, y: 10, width: 100.0, height: 8.0)
    attributedString.draw(with: positionRect, options: .usesLineFragmentOrigin, context: nil)
}

Solution

  • The issue is due to passing a CGColor instead of a UIColor for the .foregroundColor key in your attributes dictionary. The documentation states:

    In macOS, the value of this attribute is an NSColor instance. In iOS, tvOS, watchOS, and Mac Catalyst, the value of this attribute is a UIColor instance. Use this attribute to specify the color of the text during rendering. If you don’t specify this attribute, the text renders in black.

    The NSAttributedString code is attempting to call set on the provided color as indicated by the error. This is indicated in the error message showing the Objective-C syntax -[__NSCFType set]. This shows that set is being called on an object of type __NSCFType which is an internal type representing many Core Foundation (and Core Graphics) types, such as CGColor.

    In short, change the line:

    .foregroundColor: UIColor.white.cgColor
    

    to:

    .foregroundColor: UIColor.white