使用 PDFKit 创建 PDF 文档时共享问题



我正在使用PDFKit创建一个PDF文件。

PDF文档被正确创建,因为如果我尝试使用PDFView查看它,我会看到它(@IBAction func DetailButton( 可能不是...我看不到广场!

问题是我无法与UIActivityViewController共享它。(@IBAction func ShareButton(

我共享一个文本文件,它是文件路径。/var/mobile/Containers/data/Application/....../Documents/1234.pdf

此外,当我分享到"邮件"时,我如何发送默认电子邮件地址,在分享到"消息"时如何发送电话号码?

func createPDFwithPDFKit(filePath:String, share:Bool) {
let pdfTitle = "Swift-Generated PDF"
let pdfMetadata = [
// The name of the application creating the PDF.
kCGPDFContextCreator: "XXX",
// The name of the PDF's author.
kCGPDFContextAuthor: "xxx",
// The title of the PDF.
kCGPDFContextTitle: game!.name,
// Encrypts the document with the value as the owner password. Used to enable/disable different permissions.
kCGPDFContextOwnerPassword: "myPassword123"
]
// Creates a new PDF file at the specified path.
UIGraphicsBeginPDFContextToFile(filePath, CGRect.zero, pdfMetadata)
// Creates a new page in the current PDF context.
UIGraphicsBeginPDFPage()
// Default size of the page is 612x72.
let pageSize = UIGraphicsGetPDFContextBounds().size
let font = UIFont.preferredFont(forTextStyle: .largeTitle)
// Let's draw the title of the PDF on top of the page.
let attributedPDFTitle = NSAttributedString(string: pdfTitle, attributes: [NSAttributedString.Key.font: font])
let stringSize = attributedPDFTitle.size()
let stringRect = CGRect(x: (pageSize.width / 2 - stringSize.width / 2), y: 20, width: stringSize.width, height: stringSize.height)
attributedPDFTitle.draw(in: stringRect)
// Closes the current PDF context and ends writing to the file.
UIGraphicsEndPDFContext()
if share {
let vc = UIActivityViewController(activityItems: [filePath], applicationActivities: [])
vc.excludedActivityTypes = [
UIActivity.ActivityType.assignToContact,
UIActivity.ActivityType.saveToCameraRoll,
UIActivity.ActivityType.postToFlickr,
UIActivity.ActivityType.postToVimeo,
UIActivity.ActivityType.postToTencentWeibo,
UIActivity.ActivityType.postToTwitter,
UIActivity.ActivityType.postToFacebook,
UIActivity.ActivityType.openInIBooks
]
present(vc, animated: true, completion: nil)
}
}
@IBAction func ShareButton(_ sender: UIBarButtonItem) {

alert.addAction(UIAlertAction(title: "Exporter au format PDF", style: .default, handler: { _ in
let fileName = "1234.pdf"
let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let filePath = (documentsDirectory as NSString).appendingPathComponent(fileName) as String
self.createPDFwithPDFKit(filePath:filePath, share:true)
}))
alert.addAction(UIAlertAction.init(title: "Annuler", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
@IBAction func DetailButton(_ sender: UIBarButtonItem) {
// Create and add a PDFView to the view hierarchy.
let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let filePath = (documentsDirectory as NSString).appendingPathComponent("scores de '" + game!.name + "'.pdf") as String
self.createPDFwithPDFKit(filePath:filePath, share:false)
//View the PDF
let pdfView = PDFView(frame: view.bounds)
pdfView.autoScales = true
pdfView.displayMode = .singlePageContinuous
view.addSubview(pdfView)
// Create a PDFDocument object and set it as PDFView's document to load the document in that view.
let pdfDocument = PDFDocument(url: URL(fileURLWithPath: filePath))!
pdfView.document = pdfDocument
}

在我自己使用的PDFKit中,我创建了PDF文本作为NSMutableAttributedString的实例(就像你所做的那样(,但随后将其封装在UISimpleTextPrintFormatter的实例中。此对象处理文档的格式设置,尤其是在需要分页符时。此实例用于初始化 UIPrintPageRenderer 的实例。该对象"知道"页面大小、页面内的可打印区域和打印格式化程序。调用 UIGraphicsBeginPDFContextToData 后,您可以调用这些对象来逐页渲染 PDF。

显然这里有很多事情要做,所以我写了一个简单的应用程序来测试它。该场景有两个控件,一个系统样式的"共享"按钮(在导航栏中(和一个覆盖整个安全区域的UIView实例,并声明为"PDFView"类型。PDF 仅包含文本:"这是 PDF 文件中的文本。以下视图控制器逻辑提供了如何显示 PDF(在viewDidLoad方法中(以及如何完成共享(在activityButton操作中(的示例:

import UIKit
import PDFKit
class PDFViewController: UIViewController {
// MARK: iVars
private var reportBuffer = NSMutableData()
// MARK: outlets and actions
@IBOutlet weak var pdfReportView: PDFView!
@IBAction func activityButton(_ sender: Any)
{
let activityViewController =
getActivityViewController()
self.present( activityViewController,
animated: true,
completion: nil )
}
// MARK: - Action convenience functions
private func getActivityViewController() -> UIActivityViewController
{
let manager = FileManager.default
let path = pdfURL.path
if manager.fileExists(atPath: path ) {
do {
try manager.removeItem(at: pdfURL )
} catch {
fatalError()
}
}
do {
try reportBuffer.write(to: pdfURL, options: [.atomic])
} catch {
fatalError()
}
let activityVC =
UIActivityViewController( activityItems: [ pdfURL ],
applicationActivities: nil)
activityVC.completionWithItemsHandler =
{
[weak self] activity, wasCompleted, returnedItems, error in
if manager.fileExists(atPath: path ) {
do {
try manager.removeItem(at: self!.pdfURL )
} catch {
fatalError()
}
}
}
activityVC.popoverPresentationController?.sourceView =
self.pdfReportView
activityVC.modalPresentationStyle = .popover
return activityVC
}
// MARK: lifecycle
override func viewDidAppear(_ animated: Bool)
{
super.viewDidAppear( animated )
// create PDF content
let report =
NSMutableAttributedString(string: "This is text in a PDF file." )
// create renderer
let renderer = UIPrintPageRenderer()
renderer.setValue( NSValue( cgRect: paperRect ),
forKey: "paperRect" )
renderer.setValue( NSValue( cgRect: printableRect ),
forKey: "printableRect" )
let printFormatter =
UISimpleTextPrintFormatter( attributedText: report )
renderer.addPrintFormatter(printFormatter,
startingAtPageAt: 0)
// draw the PDF into an NSMutableData buffer
UIGraphicsBeginPDFContextToData( reportBuffer,
paperRect,
nil )
let pageRange = NSMakeRange( 0, renderer.numberOfPages )
renderer.prepare( forDrawingPages: pageRange )
let bounds = UIGraphicsGetPDFContextBounds()
for i in 0 ..< renderer.numberOfPages {
UIGraphicsBeginPDFPage()
renderer.drawPage( at: i, in: bounds )
}
UIGraphicsEndPDFContext()
// display the PDF
if let document =
PDFDocument( data: reportBuffer as Data )
{
pdfReportView.document = document
}
}
// MARK: - constants
private struct Page
{
static let size =
CGSize( width: 612.0, height: 792.0 )
static let margins =
UIEdgeInsets(top: 72.0,
left: 72.0,
bottom: 72.0,
right: 72.0)
}
private let printableRect =
CGRect(x: Page.margins.left,
y: Page.margins.top,
width: Page.size.width
- Page.margins.left
- Page.margins.right,
height: Page.size.height
- Page.margins.top
- Page.margins.bottom)
private let paperRect =
CGRect( x: 0.0,
y: 0.0,
width: Page.size.width,
height: Page.size.height )
private var pdfURL: URL {
let manager = FileManager.default
let url = manager.urls(for: .cachesDirectory,
in: .userDomainMask).first!
return url.appendingPathComponent("temporary.pdf") as URL
}
}

旁注:我对你的代码逻辑有点困惑。您使用"ShareButton"来显示警报,而警报又具有用于调用UIActivityViewController实例的按钮。您的业务需求可能决定了这种方法,但通常用户会发现这出乎意料地复杂。点击共享按钮(系统图标是一个带有突出向上箭头的正方形(通常会直接调用 UIActivityViewController 的实例。也就是说,没有干预警报。

编辑:我只能让邮件和消息共享在真实设备上工作。没有一个模拟器设备在UIActivityViewController弹出窗口上提供邮件或消息选项(尽管消息可用,至少在iPad Air模拟器上(。

最新更新