Crash when printing a document from UIActivityViewController or QLPreviewController on iOS 16

Seems like the printing doesn't appear to be worked correctly on iOS 16.

We've been getting a lot of crash reports related to printing since iOS 16 was released, for instance

Unfortunately, we are unable to reproduce those crashes.

This article says that SEGV_MAPERR crash is due to an invalid memory fetch. For this reason, we decided to debug our app with the Address Sanitizer tool enabled in Xcode. As a result, we found out that almost every time the app accesses a freed heap region when the print UI is presented.

The were able to reproduce 2 cases in a separated project:

  • Printing a docx file from QLPreviewController
  • Printing the same file from UIActivityViewController passing WKWebView.viewPrintFormatter as an activity item.

In order to get the error, once you get to the print UI start scrolling the document preview. See the sample code bellow:

import UIKit
import WebKit
import QuickLook

final class PrintCrashViewController: UIViewController {
    private let webView = WKWebView()

    /* 27 page document from the app bundle */
    private lazy var docFileURL = URL(fileURLWithPath: Bundle.main.path(forResource: "description", ofType: "docx")!)
    
    override func loadView() {
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        navigationItem.rightBarButtonItems = [
            UIBarButtonItem(title: "QL", style: .plain, target: self, action: #selector(openQLPreview)),
            UIBarButtonItem(title: "Share", style: .plain, target: self, action: #selector(openActivityVC))
        ]

        webView.loadFileURL(docFileURL, allowingReadAccessTo: docFileURL)
    }
    
    @objc private func openActivityVC() {
        let items: [Any] = [docFileURL, webView.viewPrintFormatter()]
        let activityVC = UIActivityViewController(activityItems: items, applicationActivities: nil)
        present(activityVC, animated: true)
    }
    
    @objc private func openQLPreview() {
        let qlPreviewVC = QLPreviewController()
        qlPreviewVC.dataSource = self
        present(qlPreviewVC, animated: true)
    }
}

extension PrintCrashViewController: QLPreviewControllerDataSource {
    func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
        1
    }
    
    func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
        docFileURL as NSURL
    }
}

Both approaches have been in our app for years.

one more post about crash when printing on iOS 16

Crash when printing a document from UIActivityViewController or QLPreviewController on iOS 16
 
 
Q