2

I am trying to share an image of a view through the Share Sheet. This is what i am doing.

One defines an extension to UIView and View where one utilizes the UIGraphicsImageRenderer to output an UIImage and modifies the .asImage to output the picture as an UIImage.

It seems to me the simplest approach to making it work. But the image is not showing in the ShareSheet.

import SwiftUI

struct SnapshottingAPI: View {
    @State private var isShareSheetShowing = false
    let imageSize: CGSize = CGSize(width: 1000, height: 1000)
    
    var body: some View {
        VStack {
            
            ZStack {
                Color.blue
                Circle()
                    .fill(Color.red)
            }
            .frame(width: 300, height: 300)
            
            Text("text")
            Button(action: shareButton){
                Image(systemName: "square.and.arrow.up")
                    .frame(width: 35, height: 35)
            }
        }
    }
    
    func shareButton() {
        isShareSheetShowing.toggle()
        let highresImage = self.asImage(size: imageSize)
        let outputimage = Image(uiImage: highresImage)
        let items: [Any] = [outputimage]
        
        let av = UIActivityViewController(activityItems: items, applicationActivities: nil)
        UIApplication.shared.windows.first?.rootViewController!.present(av, animated: true, completion: nil)
    }
}


extension UIView {
    func asImage() -> UIImage {
        let format = UIGraphicsImageRendererFormat()
        format.scale = 1
        return UIGraphicsImageRenderer(size: self.layer.frame.size, format: format).image { context in
            self.drawHierarchy(in: self.layer.bounds, afterScreenUpdates: true)
        }
    }
}


extension View {
    func asImage(size: CGSize) -> UIImage {
        let controller = UIHostingController(rootView: self)
        controller.view.bounds = CGRect(origin: .zero, size: size)
        let image = controller.view.asImage()
        return image
    }
}
struct SnapshottingAPI_Previews: PreviewProvider {
    static var previews: some View {
        SnapshottingAPI()
    }
}

View

AndiAna
  • 854
  • 6
  • 26
  • This might help you: https://stackoverflow.com/a/64358617/8697793 – pawello2222 Feb 19 '21 at 10:05
  • thanks. but if i use the self.uiimage inside the shareButton() and convert it to Image using Image(uiImage: self.uiimage!) the share is still empty and not showing a picture. Can you check it for me? I let outputimage = Image(uiImage: self.uiimage!) in the code above. – AndiAna Feb 19 '21 at 14:08
  • Please try the exact extensions from the link above - e.g. your `extension UIView { func asImage() -> UIImage` works differently. – pawello2222 Feb 19 '21 at 14:13
  • thanks but its too complicated for me to piece together. i am just very new to SwiftUI. – AndiAna Feb 19 '21 at 16:01

1 Answers1

1

I found a way to do it using some other posts. This is simple enough for me. Albeit its missing the thumbnail image in the ShareSheet

import SwiftUI
import LinkPresentation

extension UIView {
    func asImage(rect: CGRect) -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: rect)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }
}

struct SO1: View {
    @State private var rect1: CGRect = .zero
    @State private var uiimage: UIImage? = nil
    @State private var isShareSheetShowing = false

    var body: some View {
        VStack {
            HStack {
                VStack {
                    Text("LEFT")
                    Text("VIEW")
                }
                .padding(20)
                .background(Color.green)
                .border(Color.blue, width: 5)
                .background(RectGetter(rect: $rect1))
                
                Button(action: shareButton){
                    Image(systemName: "square.and.arrow.up")
                        .frame(width: 35, height: 35)
                }

            }

        }

    }
    
    func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        return ""
    }

    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
        return nil
    }

    func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? {
        let image = UIImage(named: "YourImage")!
        let imageProvider = NSItemProvider(object: image)
        let metadata = LPLinkMetadata()
        metadata.imageProvider = imageProvider
        return metadata
    }
    
    func shareButton() {
        isShareSheetShowing.toggle()
        self.uiimage = UIApplication.shared.windows[0].rootViewController?.view.asImage(rect: self.rect1)
        //let outputimage = Image(uiImage: self.uiimage!)
        let items: [Any] = [self.uiimage!, self, "Test Text"]
        let av = UIActivityViewController(activityItems: items, applicationActivities: nil)
        UIApplication.shared.windows.first?.rootViewController!.present(av, animated: true, completion: nil)
    }
}

struct RectGetter: View {
    @Binding var rect: CGRect

    var body: some View {
        GeometryReader { proxy in
            self.createView(proxy: proxy)
        }
    }

    func createView(proxy: GeometryProxy) -> some View {
        DispatchQueue.main.async {
            self.rect = proxy.frame(in: .global)
        }

        return Rectangle().fill(Color.clear)
    }
}

struct SO1_Previews: PreviewProvider {
    static var previews: some View {
        SO1()
    }
}
AndiAna
  • 854
  • 6
  • 26