Correctly set the PopOverViewController in SwiftUI

Viewed 363

In my iOS App I've got the problem that the App crashes on iPad when I want to show a UIActivityViewController. I've found out that this happens because of the PopoverPresentationController and that I should set it to my view or button.

My code looks like this:

@State var alert = ActionSheet(title: Text("Error"))

var body: some View {
    VStack() {
        Button(action: {
        self.showSheet.toggle()
        }) {
        Image(systemName: "ellipsis")
        }
        .actionSheet(isPresented: $showSheet) {
            self.alert
        }
    }.onAppear(){
        alert = ActionSheet(
            title: Text("Auftrag"),
            buttons: [
                .cancel(Text("Close")),
                .default(Text("Share")) { openActionSheet() },
        )
    }
}

func openActionSheet() {
    let contextString = "TEST"

    let print = UIMarkupTextPrintFormatter(markupText: contextString)
            
    let render = UIPrintPageRenderer()
    render.addPrintFormatter(print, startingAtPageAt: 0)

    let page = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
    render.setValue(page, forKey: "paperRect")
    render.setValue(page, forKey: "printableRect")

    let pdfData = NSMutableData()
    UIGraphicsBeginPDFContextToData(pdfData, .zero, nil)

    for i in 0..<render.numberOfPages {
    UIGraphicsBeginPDFPage();
        render.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())
    }
    UIGraphicsEndPDFContext();

    let av = UIActivityViewController(activityItems: [pdfData], applicationActivities: nil)

    av.popoverPresentationController?.sourceView = view
    
    UIApplication.shared.windows.first?.rootViewController?.present(av, animated: true, completion: nil)
}

The line av.popoverPresentationController?.sourceView = view is what prevents the crash in all the other questions I've found.
In my case I get the error Cannot find 'view' in scope.

Can someone please explain me why?

1 Answers

You can specify the av.popoverPresentationController.sourceView like this:

    if UIDevice.current.userInterfaceIdiom == .pad {
        av.popoverPresentationController?.sourceView = UIApplication.shared.windows.first
        av.popoverPresentationController?.sourceRect = CGRect(x: UIScreen.main.bounds.width / 2.1, y: UIScreen.main.bounds.height / 2.3, width: 200, height: 200)
    }
Related