I currently working on an iOS app that requires me to support iOS 15+.
I’ve developed a custom SwiftUI button view called ShareButton
The goal of this button is to make the share functionality reusable across the app so that I can add this ShareButton
to any view and have the ability to share it’s contents.
I have a navigation router that centralizes transitions, presentations and pushes to other screens and the code in this router is UIKit based.
I use a UIActivityViewController
to share.
This is my code:
struct ShareButton: View {
let url: URL?
var body: some View {
shareButton
.simultaneousGesture(TapGesture().onEnded() {
completion?()
})
}
@ViewBuilder
private var shareButton: some View {
if let url {
Button {
navigationRouter.presentActivityViewController(activityItems: [url],
applicationActivities: [])
} label: {
Image(systemName: Constants.Image.shareIcon)
}
}
}
And in my router I have something like this:
func presentActivityViewController(activityItems: [Any], applicationActivities: [UIActivity]?) {
let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: applicationActivities)
activityViewController.popoverPresentationController?.sourceView = UIView()
activityViewController.presentInKeyWindowPresentedController()
}
On the iPhone, this works well, however, on the iPad, the share popover originates on the top left of the screen.
I can see that my popoverPresentationController
sourceView
is a random UIView
, so this behavior makes sense and brings me to my first question, is there a way to pass my ShareButton
here as a UIView
instead ?
What i tried was:
- changing the sourceView to the top most view controller
- figuring out the frame of my button using
GeometryReader
and passing it to the presentActivity function - Passing the frame to the
presentActivity
function and using it as thesourceRect
of thepopoverPresentationController
This does give me results that are quite close to what I want, however, it is not perfect as the popover hides the button.
So my questions are:
- What would be the best way to achieve this using my architecture ?
- Is it possible to pass the swiftUI View as a UIView to the
popoverPresentationController.sourceView
?