0

I'm coding in swiftUI, and I'm trying to create a button that first generates a new image and then opens a ShareSheet where the new image can be shared. However, with the code below, only the description is shared. Can someone please help me with what is wrong?

import SwiftUI import UIKit struct ShareSheetViewTESTER: UIViewControllerRepresentable { var imageToShare: UIImage var descriptionToShare: String var itemsToShare: [Any] { return [imageToShare, descriptionToShare] } func makeUIViewController(context: Context) -> UIActivityViewController { let activityVC = UIActivityViewController(activityItems: itemsToShare, applicationActivities: nil) return activityVC } func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) { } } struct FriendsView: View { @State private var showShareSheet = false @State private var image = UIImage(named: "Kort")! @State private var description = "Some text here" @State private var generatedImage: UIImage? var body: some View { VStack { Button(action: { generateImage() self.showShareSheet = true }) { Image(systemName: "square.and.arrow.up") .frame(width: 25, height: 25) } .sheet(isPresented: $showShareSheet) { ShareSheetViewTESTER(imageToShare: generatedImage ?? self.image, descriptionToShare: self.description) } } } func generateImage() { if let imageFromBundle = UIImage(named: "Kort") { let textToOverlay = "Text to be put on the photo" let imageRenderer = UIGraphicsImageRenderer(size: imageFromBundle.size) let generatedImage = imageRenderer.image { context in imageFromBundle.draw(at: .zero) let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.alignment = .center paragraphStyle.lineBreakMode = .byWordWrapping let attributes: [NSAttributedString.Key: Any] = [ .font: UIFont.systemFont(ofSize: 20), .foregroundColor: UIColor.black, .paragraphStyle: paragraphStyle ] let textNSString = textToOverlay as NSString let textSize = textNSString.boundingRect(with: CGSize(width: imageFromBundle.size.width, height: .greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: attributes, context: nil).size let textRect = CGRect(x: 0, y: 170, width: imageFromBundle.size.width, height: textSize.height) textNSString.draw(in: textRect, withAttributes: attributes) } self.generatedImage = generatedImage } } } struct FriendsView_Previews: PreviewProvider { static var previews: some View { FriendsView() } } 

I have tried several other solutions, but i can't get anything to work. I would be realy happy if someone can help me out here.

1
  • .sheet(isPresented: $showShareSheet) { [generatedImage, description, image] in ... Commented Jan 28, 2024 at 20:19

1 Answer 1

1

It appears that the image and description are being shared correctly (e.g., when saving to files in SwiftUI's preview), but the preview in the share sheet does not include the sharing image. This issue arises due to the way UIActivityViewController manages the presentation of shared items. To ensure the shared content is displayed accurately in the share sheet preview, a custom class conforming to the UIActivityItemSource protocol can be implemented. This approach offers enhanced control over the shared content and its metadata.

Here's a refined solution:

import UIKit import LinkPresentation // Custom class representing the item to be shared final class ActivityItem: NSObject { let name: String let image: UIImage init(name: String, image: UIImage) { self.name = name self.image = image } } // Conforming to UIActivityItemSource for customized sharing extension ActivityItem: UIActivityItemSource { func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any { return image } func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? { return image } // Providing metadata for link presentation func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? { let metaData = LPLinkMetadata() metaData.title = name metaData.imageProvider = NSItemProvider(object: image) return metaData } } 

Adjust your itemsToShare property in ShareSheetViewTESTER to include an instance of ActivityItem:

var itemsToShare: [Any] { [ActivityItem(name: descriptionToShare, image: imageToShare), descriptionToShare] } 

This modification ensures that the UIActivityViewController receives the image in a format that it can correctly process for both sharing and previewing in the share sheet, while maintaining the correct sharing functionality as observed in file-saving scenarios.

Sign up to request clarification or add additional context in comments.

1 Comment

However, my new problem is that the sharesheet is opened before the function that generates the image has finished running, so the generated image is not included. However, if I press the share button again, it comes up, because the image has been generated and updated.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.