Insert Image into SwiftUI Text
Reading time: 1 min
This recipe shows how to insert an Image into SwiftUI Text, so that the resulting view is still a Text
instance.
The end result looks like this:
This solution works for SwiftUI 2+ (iOS 14+, macOS 11+).
Text
has an initializer that takes an Image
and converts it into a Text
, which can then be concatenated with other Text
s into a single Text
:
(Text("This image")
+ Text(Image("icon")) // HERE
+ Text("is our logo."))
.font(.title)
This all works fine until you need to resize the image. Using the frame
modifier results in a View
, which then can't be passed into a Text
initializer:
// THIS DOESN'T WORK
(Text("This image")
+ Text(Image("icon").resizable().frame(width: 32, height: 32))
+ Text("is our logo."))
.font(.title)
The trick to make this work is to use the method from this recipe, which converts any View
into an UIImage
. Here's a quick extension that captures the functionality of resizing an Image
while also returning an Image
:
extension Image {
func resizedAsImage(width: CGFloat? = nil,
height: CGFloat? = nil) -> Image {
Image(uiImage: self
.resizable()
.frame(width: width, height: height)
.snapshot) // check the other recipe for this extension
}
}
Then, you can insert a resized image into any Text
:
(Text("This image")
+ Text(Image("icon").resizedAsImage(width: 96, height: 96))
+ Text("is our logo."))
.font(.title)
What doesn't work - using AttributedString
Some of you may know that in UIKit, it's possible to insert an image into a Label
using NSAttributedString
that wraps an NSTextAttachment
, like this:
let imageAttachment = NSTextAttachment(image: UIImage(named: "icon")!)
let imageString = NSAttributedString(attachment: imageAttachment)
Then, theoretically, you could convert NSAttributedString
into an AttributedString
which you can then plug into a Text
:
let attrStr = try! AttributedString(myString, including: \.uiKit)
...
Text(attrStr)
However, this doesn't work and the image isn't shown. The issue isn't explicitly documented or explained anywhere.