the nstextattachment images are not dynamic light or dark mode

I think that’s unfortunately the normal behavior, but I considered it as a forgotten feature non-dev by Apple.

The only way I got currently, is to listen to func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) to detect the mode change.

Then, you can either reconstruct your NSAttributedString, or enumerate over it and update it when needed.

With a enumeration, ie update only what’s needed, and not regenerate the whole NSAttributedString:

In your initial attachment creation:

let attachment = NSTextAttachment(image: asset.image(with: traitCollection))
let attachmentCharacter = NSAttributedString(attachment: attachment)

Side note: I used asset.image(with: traitCollection) instead of image1, else when starting with dark mode, your image will be of light mode instead. So this should set the correct image.

Then, I’d update it with:

func switchAttachment(for attr: NSAttributedString?) -> NSAttributedString? {
    guard let attr = attr else { return nil }
    let mutable = NSMutableAttributedString(attributedString: attr)
    mutable.enumerateAttribute(.attachment, in: NSRange(location: 0, length: mutable.length), options: []) { attachment, range, stop in
        guard let attachment = attachment as? NSTextAttachment else { return }
        guard let asset = attachment.image?.imageAsset else { return }
        attachment.image = asset.image(with: .current)
        mutable.replaceCharacters(in: range, with: NSAttributedString(attachment: attachment))
    }
    return mutable
}

And update when:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)        
    label.attributedText = switchAttachment(for: label.attributedText)
}

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top