[__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)
}
  • The foregroundColor in attributes doesn't take a cgColor
  • context.cgContext.setFillColor(UIColor.black.cgColor) not needed use UIColor.black.setFill() instead.

Final changes

let imageSize = CGSize(width: 400, height: 100)

let testRenderer = UIGraphicsImageRenderer(size: imageSize)

let testImage = testRenderer.image { context in

    UIColor.black.setFill()

    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]

    var attributedString = NSAttributedString(string: "This is some text",
                                              attributes: attributes)

    let drawContext = NSStringDrawingContext()
    drawContext.minimumScaleFactor = 0.5

    attributedString.draw(with: testRenderer.format.bounds, options: .usesLineFragmentOrigin,
                          context: drawContext)
}

-enjoy!

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