DEV Community

Cover image for Share Sheet UIActivityViewController within SwiftUI
Hoye Lam | 林浩意
Hoye Lam | 林浩意

Posted on

Share Sheet UIActivityViewController within SwiftUI

Personal Blog

With Growrilla 1.5.0 released, users can now share their progress more easily.

Thus I also want to share how I did it.

First, we have the make the UIActivityViewController usable with SwiftUI. Thus we are going to wrap it around a UIViewControllerRepresentable.

struct ActivityViewController: UIViewControllerRepresentable {

    @Binding var activityItems: [Any]
    var excludedActivityTypes: [UIActivity.ActivityType]? = nil

    func makeUIViewController(context: UIViewControllerRepresentableContext<ActivityViewController>) -> UIActivityViewController {
        let controller = UIActivityViewController(activityItems: activityItems,
                                                  applicationActivities: nil)

        controller.excludedActivityTypes = excludedActivityTypes

        return controller
    }

    func updateUIViewController(_ uiViewController: UIActivityViewController, context: UIViewControllerRepresentableContext<ActivityViewController>) {}
}
Enter fullscreen mode Exit fullscreen mode

Then we create a custom ViewModifer to more easily views more easily implement the sharing feature.

struct ShareSheetModifer: ViewModifier {
    @State private var showShareSheet: Bool = false
    @State var shareSheetItems: [Any] = []

    func body(content: Content) -> some View {
        content
            .contextMenu {
                Button(action: {
                    self.showShareSheet.toggle()
                }) {
                    Text("Share")
                    Image(systemName: "square.and.arrow.up")
                }
            }
            .sheet(isPresented: $showShareSheet, content: {
                ActivityViewController(activityItems: self.$shareSheetItems)
            })
    }
}
Enter fullscreen mode Exit fullscreen mode

Within my example, I’m creating this sharing feature with a context menu, but you can easily change it to being a double tap for example with onTapGesture.

Then to use it, add the modifier to your SwiftUI Element like the following with the items that you want to share.

Text("Hello, world!")
            .padding()
            .modifier(ShareSheetModifer(shareSheetItems: ["Hello, world!"]))
Enter fullscreen mode Exit fullscreen mode

While this is already okay to use, I personally don’t like to write my modifiers in this way. Thus, you can use the following extension on View.

extension View {
    func shareSheet(items: [Any], excludedActivityTypes: [UIActivity.ActivityType]? = nil) -> some View {
        self.modifier(ShareSheetModifer(shareSheetItems: items))
    }
}
Enter fullscreen mode Exit fullscreen mode

Then you use it the following way:

Text("Hello, world!")
            .padding()
            .shareSheet(items: ["Hello world!"])
Enter fullscreen mode Exit fullscreen mode

If you want to exclude activity types like for example posting the items to Facebook, you use the it the following way:

Text("Hello, world!")
                .padding()
                .shareSheet(items: ["Hello world!"], excludedActivityTypes: [.postToFacebook])
Enter fullscreen mode Exit fullscreen mode

Hope you enjoyed it!

For the full code snippet:
Share Sheet UIActivityViewController within SwiftUI · GitHub

Top comments (1)

Collapse
 
bodich profile image
Bogdan

This code is producing bottom safe area spacing. Did you manage to fix that?