@@ -87,40 +87,81 @@ class NitroHtmlPdf: HybridNitroHtmlPdfSpec {
8787
8888 var headerWebView : WKWebView ?
8989 var footerWebView : WKWebView ?
90+ var contentWebView : WKWebView ?
91+ var loadedCount = 0
92+ var totalToLoad = 1
9093
9194 if let header = options. header, headerHeight > 0 {
95+ totalToLoad += 1
9296 let hwv = WKWebView ( frame: CGRect ( x: 0 , y: 0 , width: pageSize. width, height: headerHeight) )
9397 hwv. scrollView. contentInset = . zero
9498 hwv. scrollView. contentInsetAdjustmentBehavior = . never
95- let wrappedHeader = " <!DOCTYPE html><html><head><meta name='viewport' content='width=device-width,initial-scale=1,maximum-scale=1'><style>*{margin:0!important;padding:0!important;box-sizing:border-box;}html,body{margin:0!important;padding:0!important;width:100%;height:100%;overflow:hidden;}</style></head><body> \( header) </body></html> "
99+ let wrappedHeader = " <!DOCTYPE html><html><head><meta name='viewport' content='width=device-width,initial-scale=1,maximum-scale=1'><style>*{margin:0!important;padding:0!important;box-sizing:border-box;}html,body{margin:0!important;padding:0!important;width:100%;height:100%;overflow:hidden;}svg{display:block;width:100%;height:100%;}</style></head><body> \( header) </body></html> "
100+ let delegate = WebViewDelegate {
101+ self . waitForWebViewReady ( hwv) {
102+ loadedCount += 1
103+ if loadedCount == totalToLoad {
104+ self . renderPdf ( webView: contentWebView!, headerWebView: headerWebView, footerWebView: footerWebView, options: options, continuation: continuation)
105+ containerView. removeFromSuperview ( )
106+ }
107+ }
108+ }
109+ self . activeDelegates. append ( delegate)
110+ hwv. navigationDelegate = delegate
96111 hwv. loadHTMLString ( wrappedHeader, baseURL: nil )
97112 containerView. addSubview ( hwv)
98113 headerWebView = hwv
99114 }
100115
101116 if let footer = options. footer, footerHeight > 0 {
117+ totalToLoad += 1
102118 let fwv = WKWebView ( frame: CGRect ( x: 0 , y: 0 , width: pageSize. width, height: footerHeight) )
103119 fwv. scrollView. contentInset = . zero
104120 fwv. scrollView. contentInsetAdjustmentBehavior = . never
105- let wrappedFooter = " <!DOCTYPE html><html><head><meta name='viewport' content='width=device-width,initial-scale=1,maximum-scale=1'><style>*{margin:0!important;padding:0!important;box-sizing:border-box;}html,body{margin:0!important;padding:0!important;width:100%;height:100%;overflow:hidden;}</style></head><body> \( footer) </body></html> "
121+ let wrappedFooter = " <!DOCTYPE html><html><head><meta name='viewport' content='width=device-width,initial-scale=1,maximum-scale=1'><style>*{margin:0!important;padding:0!important;box-sizing:border-box;}html,body{margin:0!important;padding:0!important;width:100%;height:100%;overflow:hidden;}svg{display:block;width:100%;height:100%;}</style></head><body> \( footer) </body></html> "
122+ let delegate = WebViewDelegate {
123+ self . waitForWebViewReady ( fwv) {
124+ loadedCount += 1
125+ if loadedCount == totalToLoad {
126+ self . renderPdf ( webView: contentWebView!, headerWebView: headerWebView, footerWebView: footerWebView, options: options, continuation: continuation)
127+ containerView. removeFromSuperview ( )
128+ }
129+ }
130+ }
131+ self . activeDelegates. append ( delegate)
132+ fwv. navigationDelegate = delegate
106133 fwv. loadHTMLString ( wrappedFooter, baseURL: nil )
107134 containerView. addSubview ( fwv)
108135 footerWebView = fwv
109136 }
110137
111138 let webView = WKWebView ( frame: CGRect ( x: 0 , y: 0 , width: pageSize. width, height: 842 ) )
112- webView. loadHTMLString ( options. html, baseURL: nil )
113139 containerView. addSubview ( webView)
140+ contentWebView = webView
114141
115- DispatchQueue . main. asyncAfter ( deadline: . now( ) + 2.5 ) {
116- self . renderPdf ( webView: webView, headerWebView: headerWebView, footerWebView: footerWebView, options: options, continuation: continuation)
117- containerView. removeFromSuperview ( )
142+ let delegate = WebViewDelegate {
143+ self . waitForWebViewReady ( contentWebView!) {
144+ loadedCount += 1
145+ if loadedCount == totalToLoad {
146+ self . renderPdf ( webView: contentWebView!, headerWebView: headerWebView, footerWebView: footerWebView, options: options, continuation: continuation)
147+ containerView. removeFromSuperview ( )
148+ }
149+ }
118150 }
151+ self . activeDelegates. append ( delegate)
152+ webView. navigationDelegate = delegate
153+ webView. loadHTMLString ( options. html, baseURL: nil )
119154 }
120155 }
121156 }
122157
123158 private func renderPdf( webView: WKWebView , headerWebView: WKWebView ? , footerWebView: WKWebView ? , options: PdfOptions , continuation: CheckedContinuation < PdfResult , Error > ) {
159+ self . activeDelegates. removeAll ( )
160+
161+ headerWebView? . layoutIfNeeded ( )
162+ footerWebView? . layoutIfNeeded ( )
163+ webView. layoutIfNeeded ( )
164+
124165 let pageSizeString = options. pageSize? . stringValue ?? " A4 "
125166 let pageSize = getPageSize ( pageSizeString, width: options. width, height: options. height)
126167
@@ -181,6 +222,32 @@ class NitroHtmlPdf: HybridNitroHtmlPdfSpec {
181222 }
182223 }
183224
225+ private func waitForWebViewReady( _ webView: WKWebView , completion: @escaping ( ) -> Void ) {
226+ let js = """
227+ (function() {
228+ if (document.readyState !== 'complete') {
229+ return false;
230+ }
231+ const images = Array.from(document.images);
232+ return images.every(img => img.complete);
233+ })();
234+ """
235+
236+ func check( ) {
237+ webView. evaluateJavaScript ( js) { result, _ in
238+ if let isReady = result as? Bool , isReady {
239+ completion ( )
240+ } else {
241+ DispatchQueue . main. asyncAfter ( deadline: . now( ) + 0.1 ) {
242+ check ( )
243+ }
244+ }
245+ }
246+ }
247+
248+ check ( )
249+ }
250+
184251 private func getPageSize( _ size: String , width: Double ? , height: Double ? ) -> CGSize {
185252 if let w = width, let h = height {
186253 return CGSize ( width: w, height: h)
@@ -235,7 +302,7 @@ class CustomPrintPageRenderer: UIPrintPageRenderer {
235302 if let headerWebView = headerWebView, customHeaderHeight > 0 {
236303 context. saveGState ( )
237304 context. translateBy ( x: 0 , y: 0 )
238- headerWebView. layer . render ( in: context )
305+ headerWebView. drawHierarchy ( in: headerWebView . bounds , afterScreenUpdates : true )
239306 context. restoreGState ( )
240307 }
241308
@@ -262,7 +329,7 @@ class CustomPrintPageRenderer: UIPrintPageRenderer {
262329 if let footerWebView = footerWebView, customFooterHeight > 0 {
263330 context. saveGState ( )
264331 context. translateBy ( x: 0 , y: pageSize. height - customFooterHeight)
265- footerWebView. layer . render ( in: context )
332+ footerWebView. drawHierarchy ( in: footerWebView . bounds , afterScreenUpdates : true )
266333 context. restoreGState ( )
267334 }
268335 }
0 commit comments