iOS应用移植macOS遇阻:无法通过代码从TXT生成PDF
解决macOS下替代iOS PDF生成API的问题
我刚完成过iOS到macOS的PDF生成功能移植,太懂你遇到的坑了——iOS里的UIGraphicsBeginPDFContextToFile是UIKit专属的API,macOS的AppKit里根本没有这个方法,得换用AppKit原生的PDF生成方案。
下面给你两种适配macOS的实现方式,从简单到复杂,按需选择:
方式一:用NSAttributedString快速生成PDF(推荐)
这种方式最简洁,适合纯文本或简单排版的场景,直接利用NSAttributedString的内置方法生成PDF数据,无需手动处理绘图上下文:
- (void)createPDF:(NSString *)fileName withContent:(NSString *)content forSize:(int)fontSize andFont:(NSString *)fontName andColor:(NSColor *)color { // 定义A4标准尺寸(点单位,对应72DPI) const CGFloat docWidth = 595.28; const CGFloat docHeight = 841.89; // 目标文件URL NSURL *fileURL = [NSURL fileURLWithPath:fileName]; // 构建富文本属性 NSDictionary *textAttrs = @{ NSFontAttributeName: [NSFont fontWithName:fontName size:fontSize], NSForegroundColorAttributeName: color }; NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:content attributes:textAttrs]; // PDF文档属性配置(可按需添加标题、作者等元数据) NSDictionary *pdfDocAttrs = @{ NSDocumentTitleAttribute: @"Generated PDF", NSExportTypeDocumentAttribute: NSPDFFileType, NSPaperSizeAttribute: NSMakeSize(docWidth, docHeight) }; // 生成PDF数据并写入文件 NSError *error = nil; NSData *pdfData = [attributedText dataFromRange:NSMakeRange(0, attributedText.length) documentAttributes:pdfDocAttrs error:&error]; if (pdfData && !error) { [pdfData writeToURL:fileURL atomically:YES]; NSLog(@"PDF生成成功:%@", fileName); } else { NSLog(@"PDF生成失败:%@", error.localizedDescription); } }
方式二:用CGContext手动绘制(适合复杂排版)
如果需要自定义页面布局、多页内容或者更精细的绘图控制,可以用Core Graphics的PDF上下文来实现,类似iOS的思路但换用AppKit的API:
- (void)createAdvancedPDF:(NSString *)fileName withContent:(NSString *)content forSize:(int)fontSize andFont:(NSString *)fontName andColor:(NSColor *)color { const CGFloat docWidth = 595.28; const CGFloat docHeight = 841.89; NSRect pageRect = NSMakeRect(0, 0, docWidth, docHeight); NSURL *fileURL = [NSURL fileURLWithPath:fileName]; // 创建PDF上下文 CGContextRef pdfContext = CGPDFContextCreateWithURL((__bridge CFURLRef)fileURL, &pageRect, NULL); if (!pdfContext) { NSLog(@"无法创建PDF上下文"); return; } // 开始新页面 CGPDFContextBeginPage(pdfContext, NULL); // 切换到AppKit的绘图上下文 NSGraphicsContext *nsContext = [NSGraphicsContext graphicsContextWithCGContext:pdfContext flipped:NO]; [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext:nsContext]; // 配置文本属性 NSFont *targetFont = [NSFont fontWithName:fontName size:fontSize]; if (!targetFont) { targetFont = [NSFont systemFontOfSize:fontSize]; // fallback到系统字体 NSLog(@"指定字体不存在,使用系统字体"); } NSDictionary *textAttrs = @{ NSFontAttributeName: targetFont, NSForegroundColorAttributeName: color }; // 绘制文本(这里简单设置边距,复杂排版需要计算换行和分页) NSPoint drawOrigin = NSMakePoint(20, docHeight - 40); // 上下左右各留20点边距 [content drawAtPoint:drawOrigin withAttributes:textAttrs]; // 结束页面并清理上下文 [NSGraphicsContext restoreGraphicsState]; CGPDFContextEndPage(pdfContext); CGPDFContextClose(pdfContext); CFRelease(pdfContext); NSLog(@"高级PDF生成完成:%@", fileName); }
关键注意点
- 字体兼容:macOS和iOS的字体名称可能有差异,比如iOS的
Helvetica在macOS里对应Helvetica Neue,可以用[NSFont fontNamesForFamilyName:@"Helvetica"]查看系统可用字体 - 颜色空间:macOS的
NSColor默认是RGB空间,和iOS一致,直接使用即可 - 多页处理:如果内容超过一页,方式二需要手动计算文本高度,判断是否分页,或者用
NSLayoutManager来自动处理分页逻辑
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

