使用UIView模板使用排版创建动态尺寸的PDF [英] Create PDF of dynamic size with typography using UIView template(s)

查看:62
本文介绍了使用UIView模板使用排版创建动态尺寸的PDF的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新手,但已经学到了很多东西,并创建了一个非常棒的(我希望)应用即将完成.我的最后一项任务是创建动态生成的用户数据的PDF.这是整个过程中最令人沮丧的部分,因为没有真正的现代清晰模板或指南. Apple的文档描述性不强(某些部分我不理解),此处的问与答和Google上的示例似乎都因情况而异.我以为我几乎可以通过使用UIScrollView来做到这一点,但最终结果是混乱的,我无法使所有内容整齐地排列起来,也没有足够的控制权.

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 data. It has been the most frustrating part of this whole process as there is no real modern clear cut template or guide. Apple's documentation isn't very descriptive (and some parts I don't understand) and the Q/A here on stack and examples on Google all seem very case specific. I thought I almost had it by using a UIScrollView but the end result was messy and I couldn't get things to line up neat enough, nor did I have enough control.

我相信我在执行此任务方面的缺陷与逻辑有关,并且对可用的API知之甚少,在这两个方面的帮助都将受到赞赏.

I believe my flaws with this task are logic related and not knowing enough about available APIs, help on either is greatly appreciated.

我已经在UIViewController的子类中动态创建了填充NSArray的用户内容.该内容由字符串和图像组成.

I have dynamically created user content filling an NSArray in a subclass of a UIViewController. That content consists of Strings and Images.

我想使用UIView(假定在.xib文件中)来创建带有PDF第一页标题信息的模板(标题信息也是动态的),此后的任何页面都可以通过代码完成,因为它实际上只是一个列表.

I would like to use a UIView (I'm presuming in a .xib file) to create a template with header information for the first page of the PDF (the header information is dynamic as well), any page after that can be done via code as it really is just a list.

我对UIGraphicsPDF ...不太了解,并希望将文本和图像绘制到PDF中,而不仅仅是拍摄视图的屏幕截图.

I have a small understanding of UIGraphicsPDF... and would like to draw the text and images into the PDF and not just take a screen shot of the view.

我遇到的麻烦是: (我在这里故意是基本的,因为到目前为止我所做的一切都无济于事)

My trouble with getting this going is: (I'm being basic here on purpose because what I have done so far has led me nowhere)

如何找出我需要多少页?

How do I find out how many pages I'm going to need?

如何确定文本是否比页面长?如何拆分文本?

How do I find out if text is longer than a page and how do I split it?

如何在PDF中绘制图像?

How do I draw images in the PDF?

如何在PDF中绘制文本?

How do I draw text in the PDF?

我该如何在PDF中同时绘制文本和图像,但如何垂直填充,以确保没有重叠并说明具有动态行数的字符串?

How do I draw both text and images in the PDF but padded vertically so there's no overlap and account for Strings with a dynamic number of lines?

如何跟踪页面?

谢谢您的阅读,我缩的因素不是太高.

Thank you for reading, I hoe the cringe factor wasn't too high.

推荐答案

所以我们开始.以下是针对带有NSView的OSX所做的,但是它很容易针对UIView进行修改(所以我想).您将需要以下支架:

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将处理单个页面进行打印

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:将单个PSPrintViews保留在一个阵列中,完成后将它们发送到(PDF)打印机

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)(从菜单中)执行打印的功能

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..<basePrintPageView.totalPages {
    printPageView = basePrintPageView.clone()  
    //Set the option for the printView for what it should draw.
    printPageView.pageNo = pageNo
    //Finally append the view to the PSPrint Object.
    printObject.printViews.append(printPageView)
  }
  printObject.printTheViews() //print all the views, each view being a 'page'.
}

这篇关于使用UIView模板使用排版创建动态尺寸的PDF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆