如何加载几个Swift Wkwebviews并知道它们何时完成

发布于 2025-01-26 16:16:15 字数 1399 浏览 2 评论 0原文

我正在使用wkwebview渲染几个(大约100)网页,然后我需要将其渲染到PDF。我正在使用createpdf wkwebview的方法来完成此操作。我在自己的Web视图中执行每个页面的原因是因为createpdf不尊重HTML中的页面破裂(据我所知)。

因此,我有一个班级开始循环以渲染每个页面:

class PrintVC: ViewController, WKNavigationDelegate {
  var pages = [Page]()

  func start(){
    //A "page" is a struct that has the string content to load each web view
    for page in pages{
      let webView = WKWebView()
      webView.navigationDelegate = self
      webView.loadHTMLString(page.content, baseURL: Bundle.main.bundleURL)
    }
  }
}

我知道该页面准备在did finish navigation中保存到PDF委托方法:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    
  let config = WKPDFConfiguration()
  config.rect = CGRect(x: 0, y: 0, width: 792, height: 612)
    
  //Create the PDF
  webView.createPDF(configuration: config){ result in
    switch result{
      case .success(let data):
        do{
          try data.write(to: URL(fileURLWithPath: "file-???.pdf"))
        }catch let error{
          print(error)
        }
      case .failure(let error):
         print(error)
      }
    }
  }
}

我遇到的麻烦是我不喜欢t知道何时完成每个页面渲染。我也不知道如何传递每个页面的名称以在文件路径中使用以保存它。

如何开始一堆wkwebview加载并知道它们何时完成?或者更好的是,如何重复使用相同的wkwebview并以相同的方式加载每个单独的页面?我认为使用相同的Web视图将更好地利用内存。

I am using WKWebView to render several (around 100) web pages that I then need to render to PDF. I am using the createPDF method of WKWebView to accomplish this. The reason I'm doing each individual page in its own web view is because createPDF doesn't respect page breaks in the HTML (as far as I know).

So I have a class where I start the loop to render each page:

class PrintVC: ViewController, WKNavigationDelegate {
  var pages = [Page]()

  func start(){
    //A "page" is a struct that has the string content to load each web view
    for page in pages{
      let webView = WKWebView()
      webView.navigationDelegate = self
      webView.loadHTMLString(page.content, baseURL: Bundle.main.bundleURL)
    }
  }
}

I know the page is ready to be saved to PDF in the didFinish navigation delegate method:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    
  let config = WKPDFConfiguration()
  config.rect = CGRect(x: 0, y: 0, width: 792, height: 612)
    
  //Create the PDF
  webView.createPDF(configuration: config){ result in
    switch result{
      case .success(let data):
        do{
          try data.write(to: URL(fileURLWithPath: "file-???.pdf"))
        }catch let error{
          print(error)
        }
      case .failure(let error):
         print(error)
      }
    }
  }
}

The trouble I'm having is I don't know when each individual page is done rendering. I also don't know how to pass each page's name to be used in the file path to save it.

How can I start a bunch of WKWebView loads and know when they are all done? Or better still, how can I reuse the same WKWebView and load each individual page in the same way? I assume using the same web view would be a better use of memory.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

温馨耳语 2025-02-02 16:16:15

如何开始一堆wkwebview加载并知道它们何时完成?

好吧,您需要确定哪种Web视图导致了调用委托方法。出于这个原因,第一个参数 - webview:wkwebview - 存在。

一种方法是将每个(Web视图,对)放入字典([wkwebview:page])中。然后启动加载:

// assume you have declared a property "self.webViewDict"
for page in pages{
  let webView = WKWebView()
  webView.navigationDelegate = self

  self.webViewDict[webView] = page
  webView.loadHTMLString(page.content, baseURL: Bundle.main.bundleURL)
}

完成加载后,您可以通过执行WebViewDict [WebView]来标识页面。然后,您应该从字典中删除Web视图:

webViewDict[webView] = nil
if webViewDict.isEmpty {
    // everything is loaded!
}

如何以相同的方式重复使用相同的wkwebview并加载每个页面?

请注意,如果您使用相同的wkwebview,则必须顺序加载页面。相同的Web视图不能同时加载多个内容。

您可以从页面中删除已加载的页面。如果您不想这样做,则可以首先将页面复制到另一个var

开始中,加载第一页:

if let firstPage = pages.first {
    webView.loadHTMLString(firstPage.content, baseURL: Bundle.main.bundleURL)
}

成功加载页面时,再次执行同样的事情:

case .success(let data):
    pages.removeFirst()
    if let firstPage = pages.first {
        webView.loadHTMLString(firstPage.content, baseURL: Bundle.main.bundleURL)
    } else {
        // we are done!
    }

How can I start a bunch of WKWebView loads and know when they are all done?

Well, you'd need to identify which web view caused the delegate method to be called. It is for this reason that the first parameter - webView: WKWebView - exists.

One way is to put each (web view, pair) into a dictionary ([WKWebView: Page]). Then start the loading:

// assume you have declared a property "self.webViewDict"
for page in pages{
  let webView = WKWebView()
  webView.navigationDelegate = self

  self.webViewDict[webView] = page
  webView.loadHTMLString(page.content, baseURL: Bundle.main.bundleURL)
}

When one finishes loading, you can identify the page by doing webViewDict[webView]. You should then remove the web view from the dictionary:

webViewDict[webView] = nil
if webViewDict.isEmpty {
    // everything is loaded!
}

how can I reuse the same WKWebView and load each individual page in the same way?

Note that if you use the same WKWebView, you'll have to load the pages sequentially. The same web view can't load multiple things at the same time.

You can just removed the loaded pages from pages. If you don't want to do that, you can copy pages to another var first.

In start, load the first page:

if let firstPage = pages.first {
    webView.loadHTMLString(firstPage.content, baseURL: Bundle.main.bundleURL)
}

When you successfully load a page, do the same thing again:

case .success(let data):
    pages.removeFirst()
    if let firstPage = pages.first {
        webView.loadHTMLString(firstPage.content, baseURL: Bundle.main.bundleURL)
    } else {
        // we are done!
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文