利用 UIKit 的 UIGraphicsBeginPDFContextToFile 開啟 PDF 上下文,逐頁繪製 UITextView 的內容,最後關閉上下文。
- (void)exportTextViewToPDF:(UITextView *)textView filePath:(NSString *)path {
// 1. 創建 PDF 上下文
UIGraphicsBeginPDFContextToFile(path, CGRectZero, nil);
// 2. 計算分頁
CGSize pageSize = CGSizeMake(595.2, 841.8); // A4 尺寸 (points)
CGFloat margin = 40;
CGRect textRect = CGRectMake(margin, margin, pageSize.width - 2*margin, pageSize.height - 2*margin);
NSAttributedString *attrText = textView.attributedText;
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrText);
CFRange range = CFRangeMake(0, attrText.length);
BOOL done = NO;
while (!done) {
// 3. 開始新頁
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, pageSize.width, pageSize.height), nil);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, 0, pageSize.height);
CGContextScaleCTM(ctx, 1.0, -1.0); // 翻轉坐標系
// 4. 繪製當前頁內容
CGMutablePathRef pathRef = CGPathCreateMutable();
CGPathAddRect(pathRef, NULL, textRect);
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, range, pathRef, NULL);
CTFrameDraw(frame, ctx);
// 5. 更新範圍
CFIndex visibleRange = CTFrameGetVisibleStringRange(frame).length;
range.location += visibleRange;
range.length -= visibleRange;
if (range.length <= 0) done = YES;
CFRelease(frame);
CFRelease(pathRef);
}
CFRelease(framesetter);
// 6. 結束
UIGraphicsEndPDFContext();
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths firstObject];
NSString *pdfPath = [docDir stringByAppendingPathComponent:@"export.pdf"];
[self exportTextViewToPDF:self.myTextView filePath:pdfPath];
需引入 CoreText.framework 並 #import <CoreText/CoreText.h>。
UIPrintPageRenderer + UIPrintInteractionController 生成 PDF(iOS 10+ 更簡單)。PDFKit (iOS 11+) 或 PSPDFKit。