I'd like to present share menu with multiple options. I've created a Menu and added all ShareLink views. I can tap the share button, but if I select a ShareLink, nothing happens. No error message.
This is the only way I can think of to create such a "share menu":
ToolbarItemGroup(placement: SwiftUI.ToolbarItemPlacement.navigationBarTrailing) {
Menu {
ShareLink(
item: URL(string: "https://www.apple.com")!,
preview: SharePreview(
"Test 123",
image: Image(systemName: "plus")
)
)
ShareLink(
item: URL(string: "https://www.microsoft.com")!,
preview: SharePreview(
"Tests 321",
image: Image(systemName: "minus")
)
)
} label: {
Image(systemName: "square.and.arrow.up")
}
}
ShareLink
inside a menu doesn't currently work. A Menu is technically a new View Controller (UIContextMenuActionsOnlyViewController
) presented over the active window. The Share Action Sheet needs a View controller to present from. When a ShareLink
inside a Menu
is tapped, it dismisses the menu VC, along with the share action sheet. You can verify this by checking the view hierarchy when a Menu is open.
One workaround is to manually create Button/MenuItem/s and show a share action sheet on button tap from the underlying View; which avoids using ShareLink directly.
Workaround:
...
ToolbarItemGroup(placement: SwiftUI.ToolbarItemPlacement.navigationBarTrailing) {
Menu {
Button(action: {
showShareSheet(url: URL("https://www.apple.com")!)
}) {
Label("Share1", systemImage: "square.and.arrow.up")
}
Button(action: {
showShareSheet(url: URL(string: "https://www.microsoft.com")!)
}) {
Label("Share2", systemImage: "square.and.arrow.up")
}
} label: {
Image(systemName: "square.and.arrow.up")
}
}
...
// UIActivityViewController can be customised.
// For examples, see https://www.hackingwithswift.com/articles/118/uiactivityviewcontroller-by-example
func showShareSheet(url: URL) {
let activityVC = UIActivityViewController(activityItems: [url], applicationActivities: nil)
UIApplication.shared.currentUIWindow()?.rootViewController?.present(activityVC, animated: true, completion: nil)
}
// utility extension to easily get the window
public extension UIApplication {
func currentUIWindow() -> UIWindow? {
let connectedScenes = UIApplication.shared.connectedScenes
.filter { $0.activationState == .foregroundActive }
.compactMap { $0 as? UIWindowScene }
let window = connectedScenes.first?
.windows
.first { $0.isKeyWindow }
return window
}
}