2

I am using iOS Charts (Daniel Gindi) to generate graphs in an iOS app and I want to be able to generate a PDF report with those graphs included in the body of the report. Can anyone explain how to go about doing this. Ideally I don't want to generate an image from the UIView that shows in the app because the size/resolution would not be suitable for the PDF document.

As I understand it there are a few options:

  1. use the graphics context for the pdf document to draw the graph on - it's not clear whether this would be possible when using the Charts library
    1. use a UIView somehow to generate the graph and generate a PDF image data from that, embed this image into the pdf report

It seems like option 1 is probably the preferred way to get best resolution/control - somewhat speculative - doing it this way means you should be able to specify the exact position and size and get the correct font sizes, line thicknesses, etc..

Using option 2 means you have to figure out the scaling between a UIView and the PDF page view and I am not sure how these would map to each other.

Can anyone provide any suggestions on the following:

  1. Is it possible to use Charts to generate graphs in a PDF document, and if so how?
  2. If not what other options are there, short of writing custom drawing code.
Duncan Groenewald
  • 8,496
  • 6
  • 41
  • 76

1 Answers1

3

OK so here is what I have done

Option 1: Using a UIView.layer to render on the PDF CGContect

func drawLineGraph(x: CGFloat, y: CGFloat)->CGRect{

    let width = (pageSize.width - 2*kBorderInset - 2*kMarginInset)/2.0 - 50.0

    let renderingRect = CGRect(x: x, y: y + 50.0, width: width, height: 150.0)

    // Create a view for the Graph
    let graphController = LineChartController(rect: renderingRect, building: self.building)

    if let currentContext = UIGraphicsGetCurrentContext() {

        let frame = graphController.chartView.frame
        currentContext.saveGState()
        currentContext.translateBy(x:frame.origin.x, y:frame.origin.y);
        graphController.chartView.layer.render(in: currentContext)
        currentContext.restoreGState()
    }
    return renderingRect
}

The graphController is just an object that has essentially the same function as the usual parent ViewController that would contain the graph. Sets the graph parameters and data.

Once that has been done the function below is called to render on the PDF page context.

A bit of translation required to put the graphs in the correct position.

Option 2: Drawing on the PDF Page CGContect

And the solution is...ta da...

func drawBarGraph(x: CGFloat, y: CGFloat)->CGRect{

        let width = (pageSize.width - 2*kBorderInset - 2*kMarginInset)/2.0 - 50.0

        let renderingRect = CGRect(x: x + width + 50, y: y + 50.0, width: width, height: 150.0)

        // Create a view for the Graph
        let graphController = BarChartController(rect: renderingRect, building: self.building)

        if let currentContext = UIGraphicsGetCurrentContext() {

            let frame = graphController.chartView.frame
            currentContext.saveGState()
            currentContext.translateBy(x:frame.origin.x, y:frame.origin.y)

            //graphController.chartView.layer.render(in: currentContext)
            graphController.chartView.draw(frame)

            currentContext.restoreGState()   

        }
        return renderingRect
    }

Since the current context is set to the PDF page's context just call the charts draw() function directly passing the frame rectangle.

What have I missed here, can it be this easy ?

You can find a copy of the generated PDF here as well as sample code.

Duncan Groenewald
  • 8,496
  • 6
  • 41
  • 76
  • but how it will bind the data ? r u sure its generating pdf with data in graph ? – CodeChanger May 21 '18 at 13:03
  • If I knew how to attach a pdf to my answer I would attach the output. I will attach a png with zoomed in view so you can see for yourself. The graphController provides the data source. I will post the controller class as well for completeness. – Duncan Groenewald May 21 '18 at 22:38
  • @CodeChanger - I have updated my answer with a link to the generated PDF file - you can check it out yourself. I will post more of the code at some point. – Duncan Groenewald May 21 '18 at 22:53