L' UIMarkupTextPrintFormatter
ne semblent pas soutenir le html img
balise. La documentation d'Apple n'est pas très informatif ici, il précise simplement que l'initialisation du paramètre est "Le balisage HTML de texte pour l'impression de formateur". Il n'y a aucune indication de ce que les balises sont pris en charge par l'impression de formateur.
Après de nombreux tests à la seule conclusion que je peux en tirer est qu' UIMarkupTextPrintFormatter
ne prend PAS en charge l'affichage des images.
D'où vient donc que de laisser les gens qui veulent la commodité de la création de PDF à partir du contenu HTML?
Donc le seul moyen que j'ai trouvé pour faire ce travail est d'utiliser un caché de la vue web que vous chargez votre contenu html, puis utiliser le web en vue de l' UIViewPrintFormatter
. Cela fonctionne, mais se sent vraiment comme un hack.
Il fonctionne bien et il va incorporer des images dans votre document PDF, mais si c'était moi, je pencherais vers l'utilisation de CoreText et de Quartz 2D que vous avez beaucoup plus de contrôle sur le processus de génération de pdf, après avoir dit que je comprends, il serait peut-être exagéré, je ne sais pas la taille ou la complexité de votre contenu html.
Pour un exemple de travail...
Le programme d'installation
Il est utile de définir une url de base pour que je puisse simplement passer dans les noms de fichiers des images, j'ai voulu l'utiliser. L'url de base est mappé à un répertoire dans l'app bundle où les images se trouvent. Vous pouvez définir votre propre emplacement.
Bundle.main.resourceURL + "www/"
Puis j'ai créé un protocole de gérer des fonctionnalités similaires. Des implémentations par défaut sont fournis par une extension comme vous pouvez le voir dans le code ci-dessous.
protocol DocumentOperations {
// Takes your image tags and the base url and generates a html string
func generateHTMLString(imageTags: [String], baseURL: String) -> String
// Uses UIViewPrintFormatter to generate pdf and returns pdf location
func createPDF(html: String, formmatter: UIViewPrintFormatter, filename: String) -> String
// Wraps your image filename in a HTML img tag
func imageTags(filenames: [String]) -> [String]
}
extension DocumentOperations {
func imageTags(filenames: [String]) -> [String] {
let tags = filenames.map { "<img src=\"\($0)\">" }
return tags
}
func generateHTMLString(imageTags: [String], baseURL: String) -> String {
// Example: just using the first element in the array
var string = "<!DOCTYPE html><head><base href=\"\(baseURL)\"></head>\n<html>\n<body>\n"
string = string + "\t<h2>PDF Document With Image</h2>\n"
string = string + "\t\(imageTags[0])\n"
string = string + "</body>\n</html>\n"
return string
}
func createPDF(html: String, formmatter: UIViewPrintFormatter, filename: String) -> String {
// From: https://gist.github.com/nyg/b8cd742250826cb1471f
print("createPDF: \(html)")
// 2. Assign print formatter to UIPrintPageRenderer
let render = UIPrintPageRenderer()
render.addPrintFormatter(formmatter, startingAtPageAt: 0)
// 3. Assign paperRect and printableRect
let page = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
let printable = page.insetBy(dx: 0, dy: 0)
render.setValue(NSValue(cgRect: page), forKey: "paperRect")
render.setValue(NSValue(cgRect: printable), forKey: "printableRect")
// 4. Create PDF context and draw
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil)
for i in 1...render.numberOfPages {
UIGraphicsBeginPDFPage();
let bounds = UIGraphicsGetPDFContextBounds()
render.drawPage(at: i - 1, in: bounds)
}
UIGraphicsEndPDFContext();
// 5. Save PDF file
let path = "\(NSTemporaryDirectory())\(filename).pdf"
pdfData.write(toFile: path, atomically: true)
print("open \(path)")
return path
}
}
Ensuite, j'ai eu ce protocole adopté par une-vue-contrôleur. La clé pour faire ce travail, c'est là, votre point de vue contrôleur doit adopter l' UIWebViewDelegate
et dans le
func webViewDidFinishLoad(_ webView: UIWebView)
vous pouvez voir le fichier pdf est créé.
class ViewController: UIViewController, DocumentOperations {
@IBOutlet private var webView: UIWebView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
webView.delegate = self
webView.alpha = 0
if let html = prepareHTML() {
print("html document:\(html)")
webView.loadHTMLString(html, baseURL: nil)
}
}
fileprivate func prepareHTML() -> String? {
// Create Your Image tags here
let tags = imageTags(filenames: ["PJH_144.png"])
var html: String?
// html
if let url = Bundle.main.resourceURL {
// Images are stored in the app bundle under the 'www' directory
html = generateHTMLString(imageTags: tags, baseURL: url.absoluteString + "www/")
}
return html
}
}
extension ViewController: UIWebViewDelegate {
func webViewDidFinishLoad(_ webView: UIWebView) {
if let content = prepareHTML() {
let path = createPDF(html: content, formmatter: webView.viewPrintFormatter(), filename: "MyPDFDocument")
print("PDF location: \(path)")
}
}
}