The goal is to utilize SwiftUI ShareLink to render, and share a specific portion of a SwiftUI View to Messages, Instagram, and other social media applications. My question is, what is the appropriate method to do so and retain all styling of that portion of the view?
struct SelectedEntryShareView: View {
let title: String
let entry: String
let entryDate: Date
@State private var renderedImage = Image("")
var body: some View {
VStack {
Spacer()
content
Spacer()
}
.frame(maxWidth: .infinity)
.background(Color("Base"))
.safeAreaInset(edge: .bottom) {
shareButtons
}
.task {
if !title.isEmpty && !entry.isEmpty {
renderedImage = renderContent(content: content)
}
}
}
}
extension SelectedEntryShareView {
var content: some View {
ScrollView {
VStack {
Text(entryDate.formatted(date: .abbreviated, time: .shortened))
.font(.callout)
.fontWeight(.semibold)
.foregroundStyle(.accent)
.padding(.top)
Text(title)
.font(.title)
.bold()
.padding(.bottom, 5)
Text(entry)
.frame(alignment: .leading)
SelectedEntryShareViewFooter()
}
.padding(.horizontal)
}
.frame(minWidth: 300, maxWidth: 400, minHeight: 200, maxHeight: 500)
.background {
RoundedRectangle(cornerRadius: 8)
.foregroundStyle(Color("Highlight"))
}
}
var shareButtons: some View {
HStack {
ShareLink(item: renderedImage, preview: SharePreview(title, image: renderedImage)) {
Image(systemName: "message.circle")
.padding()
.foregroundStyle(.white)
.background {
RoundedRectangle(cornerRadius: 8)
.foregroundStyle(.secondary)
}
}
Button {
} label: {
Image(systemName: "ellipsis.circle")
.padding()
.foregroundStyle(.white)
.background {
RoundedRectangle(cornerRadius: 8)
.foregroundStyle(.secondary)
}
}
}
.font(.title)
}
@MainActor func renderContent(content: some View) -> Image {
let renderer = ImageRenderer(content: content)
guard let image = renderer.uiImage else { fatalError() }
return Image(uiImage: image)
}
}
As you can see, I have a function which renders the content into a UIImage, then converts it to an Image. I wasn't sure what to do to pass the image to the ShareLink so I opted for a @State variable which is then changed. The current method leaves me with a blank rectangle shown below. I have also included a picture of what I want my desired output to be similar to.


Using this Hacking with Swift article. I was able to determine that I needed to add
@MainActorto the view I was attempting to useImageRendereron. This allowed me to then call my asynchronousImageRendererfunction directly inside of theShareLink.