SwiftUI: How to get the HostingController View/Content maxHeight by given width?

1k views Asked by At

I'm trying to get the maxHeigth of an UIHostingController-View/Content and know only the width. I want to create a PDF Document based on my view. Everything works fine but I don't know how to get the maxHeight of the view/content so the PDF knows how many pages "long" is my view/content.

func exportToPDF() {

        let pdfName = "document"
       
        let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let outputFileURL = documentDirectory.appendingPathComponent("\(pdfName).pdf")
        
        let printView = ProjectDetailView(viewModel: viewModel)
        let pdfVC = UIHostingController(rootView: printView)
        
//Render the view behind all other views
        let rootVC = UIApplication.shared.windows.first?.rootViewController
        rootVC?.addChild(pdfVC)
        rootVC?.view.insertSubview(pdfVC.view, at: 0)
        
        let height: CGFloat = ???? <- **Needed Height by given width of 8.5 * 72.0** 
        let width: CGFloat = 8.5 * 72.0
        
        pdfVC.view.frame = CGRect(x: 0, y: 0, width: width, height: height)
        

        let numberOfPagesThatFitVertically = Int(ceil(height / 842))
        
        //Render the PDF
        let pdfRenderer = UIGraphicsPDFRenderer(bounds: CGRect(x: 0, y: 0, width: 8.5 * 72.0, height: height))
        
        do {
            try pdfRenderer.writePDF(to: outputFileURL, withActions: { (context) in
                
                for indexVertical in 0 ..< numberOfPagesThatFitVertically
                {
                    
                    let offsetVerticalFloat = CGFloat(indexVertical) * 842
                    let offsetVertical = CGRect(x: 0, y: -offsetVerticalFloat, width: 8.5 * 72.0, height: 842)
                    
                    
                    context.beginPage(withBounds: offsetVertical, pageInfo: ["Page" : indexVertical])
                    
                    pdfVC.view.layer.render(in: context.cgContext)
                }
                
            })
            
            self.fileURL = outputFileURL
            
            
        }catch {
            //        self.showError = true
            print("Could not create PDF file: \(error)")
        }
        
        pdfVC.removeFromParent()
        pdfVC.view.removeFromSuperview()
        
  
    }

Update: Following you will find the ProjectDetailView (Print View I need the height for)

struct ProjectDetailView: View {
    
    @ObservedObject var viewModel = DetailViewModel(db: Project())
    
    var body: some View {
        VStack{
            Form{
                ImageView(image: viewModel.image, systemImageName: "photo", systemImageSize: 50, height: 250, circle: false )
                
                Section{
                    Text(viewModel.number)
                    Text(viewModel.status)
                }
                
                Section {
                    Text(viewModel.company)
                }
                
                Section(header: Text("Addresse")) {
                    HStack{
                        VStack(alignment: .leading){
                            Text(viewModel.street)
                            Text(viewModel.city)
                        }
                        
                    }
                }
            }
        }
            
        .navigationBarTitle(Text("\(viewModel.projectname)"), displayMode: .inline)
    }
}
1

There are 1 answers

4
Asperi On BEST ANSWER

Here is possible approach:

let width: CGFloat = 8.5 * 72.0
let height: CGFloat = pdfVC.view.sizeThatFits(
     CGSize(width: width, height: .greatestFiniteMagnitude)).height