You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:38:32