Swift PDFKit自定义PDF首页面表格起始位置实现咨询
实现方案
你需要动态调整每页表格的绘制区域,同时修正原有代码的重复绘制问题,具体修改如下:
1. 核心改动点
- 新增变量标记当前是否为首页面,替代原有逻辑模糊的
pdfHeaderStatus判断 - 首页面表格绘制区域使用
CGRect(x: 0, y: 150, width: pageWidth, height: pageHeight - 150)(高度减去偏移量避免内容溢出页面) - 其余页面表格绘制区域使用
CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight) - 修正原有代码中表格重复绘制的问题:原代码if块内已经绘制了一次表格,块外又重复绘制了一次,会导致首页表格渲染异常
- 针对首页和后续页面的可用高度差异,分别计算每页可容纳的表格行数,避免内容溢出
2. 修改后完整代码
class PDFCreator: NSObject { let defaultOffset: CGFloat = 20 let tableDataHeaderTitles: [String] let tableDataItems: [TableDataItem] // 将原有全局变量改为类属性,避免外部全局变量依赖 let bastarihTitle: String let bittarihTitle: String let unvanTitle: String init(tableDataItems: [TableDataItem], tableDataHeaderTitles: [String], bastarihTitle: String, bittarihTitle: String, unvanTitle: String) { self.tableDataItems = tableDataItems self.tableDataHeaderTitles = tableDataHeaderTitles self.bastarihTitle = bastarihTitle self.bittarihTitle = bittarihTitle self.unvanTitle = unvanTitle } func create() -> Data { let pageWidth = 8.5 * 72.0 let pageHeight = 11 * 72.0 // 整页渲染区域固定,仅调整表格的实际绘制区域 let fullPageRect = CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight) let renderer = UIGraphicsPDFRenderer(bounds: fullPageRect, format: UIGraphicsPDFRendererFormat()) // 分别计算首页、后续页可容纳的表格行数 let normalPageRowCount = calculateNumberOfElementsPerPage(with: fullPageRect) let firstPageRowCount = calculateNumberOfElementsPerPage(with: CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight - 150)) // 按行数分片处理表格数据 var tableDataChunked: [[TableDataItem]] = [] var remainingItems = tableDataItems if !remainingItems.isEmpty { let firstChunkCount = min(firstPageRowCount, remainingItems.count) tableDataChunked.append(Array(remainingItems[0..<firstChunkCount])) remainingItems.removeFirst(firstChunkCount) while !remainingItems.isEmpty { let chunkCount = min(normalPageRowCount, remainingItems.count) tableDataChunked.append(Array(remainingItems[0..<chunkCount])) remainingItems.removeFirst(chunkCount) } } let data = renderer.pdfData { context in var isFirstPage = true for tableDataChunk in tableDataChunked { context.beginPage() let tableRect: CGRect if isFirstPage { // 首页表格从y=150位置开始绘制 tableRect = CGRect(x: 0, y: 150, width: pageWidth, height: pageHeight - 150) // 绘制首页页眉 let baslikTasarım = [ NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 17), NSAttributedString.Key.foregroundColor: UIColor(red: 32.0/255.0, green: 161.0/255.0, blue: 218.0/255.0, alpha: 1.0) ] let altBaslık = [ NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 11), NSAttributedString.Key.foregroundColor: UIColor.black ] let unvanTarih = [ NSAttributedString.Key.font: UIFont.systemFont(ofSize: 11), NSAttributedString.Key.foregroundColor: UIColor.black ] let image = UIImage(named: "forgotpassword") let che = "CARİ HESAP EKSTRESİ" let text = "TARİH: " let alici = "ALICI: " let tarih = "\(bastarihTitle) - \(bittarihTitle)" let unvans = "\(unvanTitle)" // 若原有页眉坐标显示正常,可保留原来的负数值坐标 che.draw(at: CGPoint(x: 30, y: -120), withAttributes: baslikTasarım) alici.draw(at: CGPoint(x: 30, y: -70), withAttributes: altBaslık) text.draw(at: CGPoint(x: 30, y: -20), withAttributes: altBaslık) image?.draw(at: CGPoint(x: 300, y: -120)) tarih.draw(at: CGPoint(x: 110, y: -20), withAttributes: unvanTarih) unvans.draw(at: CGPoint(x: 110, y: -70), withAttributes: unvanTarih) isFirstPage = false } else { // 后续页表格从y=0位置开始绘制 tableRect = fullPageRect } // 传入动态计算的表格区域绘制表格 let cgContext = context.cgContext drawTableHeaderRect(drawContext: cgContext, pageRect: tableRect) drawTableHeaderTitles(titles: tableDataHeaderTitles, drawContext: cgContext, pageRect: tableRect) drawTableContentInnerBordersAndText(drawContext: cgContext, pageRect: tableRect, tableDataItems: tableDataChunk) } } return data } func calculateNumberOfElementsPerPage(with pageRect: CGRect) -> Int { let rowHeight = (defaultOffset * 3) let number = Int((pageRect.height - rowHeight) / rowHeight) return number } // 以下三个表格绘制方法原有逻辑无需修改,直接接收传入的pageRect参数即可 func drawTableHeaderRect(drawContext: CGContext, pageRect: CGRect) { // 原有实现保留 } func drawTableHeaderTitles(titles: [String], drawContext: CGContext, pageRect: CGRect) { // 原有实现保留 } func drawTableContentInnerBordersAndText(drawContext: CGContext, pageRect: CGRect, tableDataItems: [TableDataItem]) { // 原有实现保留 } }
内容的提问来源于stack exchange,提问作者MFEkmen
相关产品推荐
相关产品推荐

