Xcode
iOS
Swift

Swift5 UILabelに画像(UIImage)を表示する NSAttributedString NSTextAttachment

qiitaの記事がobjcだったのでサクッとコピペで動かしたい方に最新版のコードを共有


UILabelにUIImageを表示する方法

①NSTextAttachmentを作成する。

②NSTextAttachmentからNSAttributedStringを作成する。

③UILabelのattributedTextに指定する。

画像のサイズや表示位置は①で調整します

今回は実際に起こりそうなものとして、ラベルの末尾に画像を表示してみます

スクリーンショット 2019-05-10 11.59.12.png


override func viewDidLoad() {
super.viewDidLoad()

let label = UILabel()
view.addSubview(label)
label.textAlignment = .center
label.frame.size = .init(width: view.bounds.width-20, height: 50)
label.center = view.center
label.font = .systemFont(ofSize: 30)

let text = "labelに犬を表示する"
let image = UIImage(named: "dog.jpg")!
let font = label.font!
let size = CGSize(width: 30, height: 30)

let attachment = NSTextAttachment()
attachment.image = image

let y = (font.capHeight-size.height).rounded() / 2
attachment.bounds.origin = CGPoint(x: 0, y: y)
attachment.bounds.size = size

let imageAttribute = NSAttributedString(attachment: attachment)
let mutableString = NSMutableAttributedString(string: text)
mutableString.insert(imageAttribute, at: text.count)

label.attributedText = mutableString
}

attachmentにsizeを指定すると表示されます。ただそれだと、画像が表示される高さがずれてしまうので、

今回は中央に揃うように高さを調整しました。

当たり前ですがinsertする場所をずらせば中央に表示できます

スクリーンショット 2019-05-10 12.00.20.png

デスクトップに犬の写真しかなかったですが、例えば仮想通貨の保有量+💶(通過のアイコン)スコア+👑(王冠やメダル)などが考えられると思います。

結構コード量が多くてとっつきにくい気もします。

うまい感じに共通化したいですが高さを揃えるにはUILabelのfontと表示したい画像のサイズの情報が必要になってきます。

UILabelのextensionにするのもなんか違う気がしますが一応

extension UILabel {

func appendImageToTail(_ image: UIImage, size: CGSize) {
guard let lastIndex = text?.count else { return }
let imageAttachment = createImageAttachment(
font: font,
image: image,
size: size
)
let imageAttribute = NSAttributedString(attachment: imageAttachment)
let mutableString = NSMutableAttributedString(string: text!)
mutableString.insert(imageAttribute, at: lastIndex)
attributedText = mutableString
}

private func createImageAttachment(font: UIFont, image: UIImage, size: CGSize) -> NSTextAttachment {
let attachment = NSTextAttachment()
attachment.image = image
let y = (font.capHeight-size.height).rounded() / 2
attachment.bounds.origin = CGPoint(x: 0, y: y)
attachment.bounds.size = size
return attachment
}
}

ラベルの上にsizeや表示位置の調整についてはこちらを参考にしました。