Create PDF of dynamic size with typography using UIView template(s)

前端 未结 2 1584
花落未央
花落未央 2021-02-11 05:18

I\'m new but have managed to learn a lot and create a pretty awesome (I hope) app that\'s near completion. One of my last tasks is to create a PDF of dynamically generated user

2条回答
  •  傲寒
    傲寒 (楼主)
    2021-02-11 05:56

    So here we go. The following was made for OSX with NSView but it's easily adapatable for UIView (so I guess). You will need the following scaffold:

    A) PSPrintView will handle a single page to print

    class PSPrintView:NSView {
      var pageNo:Int = 0 // the current page
      var totalPages:Int = 0
      struct PaperDimensions {
        size:NSSize // needs to be initialized from NSPrintInfo.sharedPrintInfo
        var leftMargin, topMargin, rightMargin, bottomMargin : CGFloat
      }
      let paperDimensions = PaperDimensions(...)
    
      class func clone() -> PSPrintView {
        // returns a clone of self where most page parameters are copied
        // to speed up printing
      }
    
      override func drawRect(dirtyRect: NSRect) {
        super.drawRect(dirtyRect)
    
        // Drawing code here.
    
        // e.g. to draw a frame inside the view
        let scale = convertSize(NSMakeSize(1, 1), fromView:nil)
        var myContext = NSGraphicsContext.currentContext()!.CGContext
        CGContextSetLineWidth(myContext, scale.height)
        CGContextSetFillColorWithColor(myContext, NSColor.whiteColor().CGColor)
        CGContextFillRect (myContext, rect)
        rect.origin.x += paperDimensions.leftMargin
        rect.origin.y += paperDimensions.bottomMargin
        rect.size.width -= paperDimensions.leftMargin + paperDimensions.rightMargin
        rect.size.height -= paperDimensions.topMargin + paperDimensions.bottomMargin
        CGContextSetStrokeColorWithColor(myContext, NSColor(red: 1, green: 0.5, blue: 0, alpha: 0.5).CGColor)
        CGContextStrokeRect(myContext, rect)
    
        // here goes your layout with lots of String.drawInRect....
      }
    }
    

    B) PSPrint: will hold the single PSPrintViews in an array and when done send them to the (PDF) printer

    class PSPrint: NSView {
      var printViews = [PSPrintView]()
    
      override func knowsPageRange(range:NSRangePointer) -> Bool {
        range.memory.location = 1
        range.memory.length = printViews.count
        return true
      }
    
      func printTheViews() {
        let sharedPrintInfo = NSPrintInfo.sharedPrintInfo()
        let numOfViews = printViews.count
    
        var totalHeight:CGFloat = 0;//if not initialized to 0 weird problems occur after '3' clicks to print
        var heightOfView:CGFloat = 0
        //    PSPrintView *tempView;
    
        for tempView in printViews {
          heightOfView = tempView.frame.size.height
          totalHeight = totalHeight + heightOfView
        }
        //Change the frame size to reflect the amount of pages.
        var newsize = NSSize()
        newsize.width = sharedPrintInfo.paperSize.width-sharedPrintInfo.leftMargin-sharedPrintInfo.rightMargin
        newsize.height = totalHeight
        setFrameSize(newsize)
        var incrementor = -1 //default the incrementor for the loop below.  This controls what page a 'view' will appear on.
    
        //Add the views in reverse, because the Y position is bottom not top.  So Page 3 will have y coordinate of 0.  Doing this so order views is placed in array reflects what is printed.
        for (var i = numOfViews-1; i >= 0; i--) {
          incrementor++
          let tempView = printViews[i] //starts with the last item added to the array, in this case rectangles, and then does circle and square.
          heightOfView = tempView.frame.size.height
    
          tempView.setFrameOrigin(NSMakePoint(0, heightOfView*CGFloat(incrementor))) //So for the rectangle it's placed at position '0', or the very last page.
    
          addSubview(tempView)
        }
        NSPrintOperation(view: self, printInfo: sharedPrintInfo).runOperation()
      }
    

    C) a function to perform printing (from the menu)

    func doPrinting (sender:AnyObject) {
      //First get the shared print info object so we know page sizes.  The shared print info object acts like a global variable.
      let sharedPrintInfo = NSPrintInfo.sharedPrintInfo()
    
      //initialize it's base values.
      sharedPrintInfo.leftMargin = 0
      sharedPrintInfo.rightMargin = 0
      sharedPrintInfo.topMargin = 0
      sharedPrintInfo.bottomMargin = 0
    
      var frame = NSRect(x: 0, y: 0, width: sharedPrintInfo.paperSize.width-sharedPrintInfo.leftMargin-sharedPrintInfo.rightMargin, height: sharedPrintInfo.paperSize.height-sharedPrintInfo.topMargin-sharedPrintInfo.bottomMargin)
      //Initiate the printObject without a frame, it's frame will be decided later.
      let printObject = PSPrint ()
    
      //Allocate a new instance of NSView into the variable printPageView
      let basePrintPageView = PSPrintView(frame: frame)
      // do additional init stuff for the single pages if needed
      // ...
    
      var printPageView:PSPrintView
      for pageNo in 0..

提交回复
热议问题