Announcement: Join the Conversation
Find discussions by searching for keywords or tags.

View all tags >
Learn more about the forums >

How can create a share sheet/view with SwiftUI for iOS 13 ?

How can create a new "Share View" ( now called "Share sheet" ? ) for iOS 13 ?

In the new features of the iOS 13, we saw how the look (and possibly the way) with which we can share with other applications has changed.


As I read in this article : iOS 13: The Ars Technica review

I want to be able to display this menu with all the share options available in my SwiftUI app:



So, even easier, how can I simply share a link - a text - to another App with Swift 5 using SwiftUI?

What is the new way proposed ? What is the code that I have to write in my View to display this menu of options?


Thank you.

Up vote post of Tas-sos Down vote post of Tas-sos
Post marked as solved 5.7k views

4 Replies

It works in much the same way as in UIKit, but you'll have to use

.sheet(isPresented:content:)
to make the view appear.


What you need is the

UIActivityViewController
, which means you'll have to create a SwiftUI
UIViewControllerRepresentable
view for that. In this case it's fairly straightforward, since you're not modifying the content or maintaining any state, you're effectively wrapping the initializer. This version works for me:


struct ShareSheet: UIViewControllerRepresentable {
    typealias Callback = (_ activityType: UIActivity.ActivityType?, _ completed: Bool, _ returnedItems: [Any]?, _ error: Error?) -> Void
    
    let activityItems: [Any]
    let applicationActivities: [UIActivity]? = nil
    let excludedActivityTypes: [UIActivity.ActivityType]? = nil
    let callback: Callback? = nil
    
    func makeUIViewController(context: Context) -> UIActivityViewController {
        let controller = UIActivityViewController(
            activityItems: activityItems,
            applicationActivities: applicationActivities)
        controller.excludedActivityTypes = excludedActivityTypes
        controller.completionWithItemsHandler = callback
        return controller
    }
    
    func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {
        // nothing to do here
    }
}


In your other view, you want this to appear modally, so you use the

.sheet()
method to do so, along with an
isPresented
state variable, like so:


struct ContentView: View {
    @State private var showShareSheet = false
    
    var body: some View {
        VStack(spacing: 20) {
            Text("Hello World")
            Button(action: {
                self.showShareSheet = true
            }) {
                Text("Share Me").bold()
            }
        }
        .sheet(isPresented: $showShareSheet) {
            ShareSheet(activityItems: ["Hello World"])
        }
    }
}


One inconvenience is that it always appears full-size for me, and I'm not sure if there's something I'm supposed to do to get the half-covered appearance that occurs in most apps.


Hope this helps. I've posted a sample project on Github here: https://github.com/AlanQuatermain/SwiftUIShareSheetDemo

@Jim Dovey Thank you very much for your detailed, complete, understandable and complete answer!

As I now see your code above, implementation in SwiftUI is similar, but as a new user, - unfortunately - I had not fully understood it and had trouble with it as I had not found it anywhere in any documentation or third party example.

I didn't know how to create (override) a SwiftUI UIViewControllerRepresentable view for that.


Personally I don't mind that the (share) sheet view opens across the screen, because now I think that's the way it is in iOS 13.

I am wrong ? In the past, it was different, but I think it now opens up to full screen.

After all, "share view" is not a built-in function common to all apps and ready to use it?

I suppose it should be a standard code supported by Apple and apply to all apps. Because this is how I imagine it should be.


But thanks to you, my question has been completely resolved and I believe you will help many more people!

Really your code works perfectly for me just like I expected, I think, and I should!


Your help is incredible! Your help is incredible! Even more you upload a sample xcode project to github! I have no words!

Thanks so much for your help and detailed information!

In Photos it's full screen, because Photos includes a lot of content (specifically the option to swipe through a list of your images to select them). Inside other apps without the preview section (I tested in Reeder 3, I think Maps—a couple, anyway), it appears half-height by default, and an upward swipe will bring it to fill the screen. The choice seems to be based on the presence of the custom preview/selection section, but a quick glance at the headers and the only open-source app I remembered that used it (NetNewsWire 5) showed nothing special being done. I tried altering the presentation mode, but that seemed to be ignored: it was always 'pageForm' when I checked after presentation, and changing it in updateViewController() didn't seem to make a difference.


It's on my list of bug reports to file now. That list's getting quite long, but happily it seems that ScrollView no longer disables multi-line Text() in its contents, so that's my chief concern out of the way 😉

Actually, thinking about it, maybe the half-screen effect is enabled purely for apps not linked against iOS 13. I know that UIKit does a bunch of these sorts of checks, to keep older behavior for apps built against older SDKs.