diff --git a/ios/Classes/SwiftFlutterHtmlToPdfPlugin.swift b/ios/Classes/SwiftFlutterHtmlToPdfPlugin.swift
index b9d51d2..2382db1 100644
--- a/ios/Classes/SwiftFlutterHtmlToPdfPlugin.swift
+++ b/ios/Classes/SwiftFlutterHtmlToPdfPlugin.swift
@@ -5,6 +5,7 @@ import WebKit
public class SwiftFlutterHtmlToPdfPlugin: NSObject, FlutterPlugin{
var wkWebView : WKWebView!
var urlObservation: NSKeyValueObservation?
+ private var didFinishOnce: Bool = false
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "flutter_html_to_pdf", binaryMessenger: registrar.messenger())
@@ -12,28 +13,72 @@ public class SwiftFlutterHtmlToPdfPlugin: NSObject, FlutterPlugin{
registrar.addMethodCallDelegate(instance, channel: channel)
}
+ private func topViewController() -> UIViewController? {
+ let window: UIWindow?
+ if #available(iOS 13.0, *) {
+ window = UIApplication.shared.connectedScenes
+ .compactMap { $0 as? UIWindowScene }
+ .first(where: { $0.activationState == .foregroundActive })?
+ .windows
+ .first(where: { $0.isKeyWindow })
+ } else {
+ window = UIApplication.shared.keyWindow ?? UIApplication.shared.delegate?.window ?? nil
+ }
+
+ var vc = window?.rootViewController
+ while let presented = vc?.presentedViewController {
+ vc = presented
+ }
+ return vc
+ }
+
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "convertHtmlToPdf":
- let args = call.arguments as? [String: Any]
- let htmlFilePath = args!["htmlFilePath"] as? String
+ guard let args = call.arguments as? [String: Any],
+ let htmlFilePath = args["htmlFilePath"] as? String,
+ !htmlFilePath.isEmpty else {
+ result(FlutterError(code: "INVALID_ARGUMENTS",
+ message: "Missing htmlFilePath",
+ details: nil))
+ return
+ }
// !!! this is workaround for issue with rendering PDF images on iOS !!!
- let viewControler = UIApplication.shared.delegate?.window?!.rootViewController
- wkWebView = WKWebView.init(frame: viewControler!.view.bounds)
+ guard let viewControler = topViewController() else {
+ result(FlutterError(code: "NO_VIEW_CONTROLLER",
+ message: "Could not find a root view controller",
+ details: nil))
+ return
+ }
+
+ didFinishOnce = false
+ wkWebView = WKWebView.init(frame: viewControler.view.bounds)
wkWebView.isHidden = true
wkWebView.tag = 100
- viewControler?.view.addSubview(wkWebView)
+ viewControler.view.addSubview(wkWebView)
- let htmlFileContent = FileHelper.getContent(from: htmlFilePath!) // get html content from file
+ let htmlFileContent = FileHelper.getContent(from: htmlFilePath) // get html content from file
wkWebView.loadHTMLString(htmlFileContent, baseURL: Bundle.main.bundleURL) // load html into hidden webview
- urlObservation = wkWebView.observe(\.isLoading, changeHandler: { (webView, change) in
+ urlObservation = wkWebView.observe(\.isLoading, changeHandler: { [weak self] (webView, change) in
+ guard let self = self else { return }
+ if webView.isLoading { return }
+ if self.didFinishOnce { return }
+ self.didFinishOnce = true
+
// this is workaround for issue with loading local images
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
- let convertedFileURL = PDFCreator.create(printFormatter: self.wkWebView.viewPrintFormatter())
+ guard let wkWebView = self.wkWebView else {
+ result(FlutterError(code: "WEBVIEW_DISPOSED",
+ message: "WKWebView was disposed before PDF generation finished",
+ details: nil))
+ return
+ }
+
+ let convertedFileURL = PDFCreator.create(printFormatter: wkWebView.viewPrintFormatter())
let convertedFilePath = convertedFileURL.absoluteString.replacingOccurrences(of: "file://", with: "") // return generated pdf path
- if let viewWithTag = viewControler?.view.viewWithTag(100) {
+ if let viewWithTag = viewControler.view.viewWithTag(100) {
viewWithTag.removeFromSuperview() // remove hidden webview when pdf is generated
// clear WKWebView cache
diff --git a/pubspec.yaml b/pubspec.yaml
index db314ef..7d9450b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -4,7 +4,7 @@ version: 0.7.0
homepage: https://github.com/Afur/flutter_html_to_pdf
environment:
- sdk: '>=2.12.0 <3.0.0'
+ sdk: '>=2.12.0 <4.0.0'
flutter: ">=1.12.0"
dependencies: