如何在wkwebview中为某些指定的URL捆绑加载CSS文件?

时间:2019-03-26 03:50:18

标签: ios swift wkwebview

我有一个WKWebView。该网页从CDN加载了大部分CSS文件。但是,我想将这个经常使用的大型css文件放入应用程序捆绑包中,以便Webview加载更快。有人知道如何从捆绑包加载吗?

我不想插入CSS文件。我想将一些css文件请求重定向到我的本地文件url。

Swift版本会很棒。

谢谢。

3 个答案:

答案 0 :(得分:1)

按如下所示创建style.css文件并将其拖放到您的项目目录中

@font-face {
    font-family: "Titillium Web";
    font-weight: normal;
    src: url("TitilliumWeb-Regular.ttf")
}

@font-face {
    font-family: "Titillium Web";
    font-style: italic;
    src: url("TitilliumWeb-Italic.ttf")
}

@font-face {
    font-family: "Titillium Web";
    font-weight: bold;
    src: url("TitilliumWeb-Bold.ttf")
}
body {
    margin: 0;
    font-family: "Titillium Web";
    font-weight: normal;
    font-size: 13pt;
}

在UIViewController的viewDidLoad()中添加以下源代码

override func viewDidLoad() {
    super.viewDidLoad()

    let html = """
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. <b>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</b>
    <br>
    <i>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</i>
    <br>
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
"""

    let htmlStart = "<HTML><HEAD><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, shrink-to-fit=no\"></HEAD><BODY>"
    let htmlEnd = "</BODY></HTML>"
    let htmlString = "\(htmlStart)\(html)\(htmlEnd)"
    webView.loadHTMLString(htmlString, baseURL: Bundle.main.bundleURL)
    self.view.addSubview(webView)
  }

如下所示创建WKWebView对象并运行应用程序,它将加载内容。

  lazy var webView: WKWebView = {
    guard
      let path = Bundle.main.path(forResource: "style", ofType: "css"),
      let cssString = try? String(contentsOfFile: path).components(separatedBy: .newlines).joined()
      else {
        return WKWebView()
    }

    let source = """
    var style = document.createElement('style');
    style.innerHTML = '\(cssString)';
    document.head.appendChild(style);
    """

    let userScript = WKUserScript(source: source,
                                  injectionTime: .atDocumentEnd,
                                  forMainFrameOnly: true)

    let userContentController = WKUserContentController()
    userContentController.addUserScript(userScript)

    let configuration = WKWebViewConfiguration()
    configuration.userContentController = userContentController

    let webView = WKWebView(frame: self.view.frame,
                            configuration: configuration)
    return webView
  }()

enter image description here

答案 1 :(得分:1)

我遇到了同样的问题,为解决问题付出了很多努力,终于找到了解决办法,它的魅力十足!对我来说

我想通过使用url而不是捆绑CSS文件位置来应用CSS,

遵循步骤,

  1. 给出您的CSS文件链接,

       let cssURL "https://xyz/styles/style.css" 
    

2。将 JavaScript 注入代码样式更改为链接,如以下代码所示,

        let source = """
        var link = document.createElement('link');
        link.href = '\(url)';
        link.rel= 'stylesheet'
        document.head.appendChild(link);
        """

3。现在是时候将JS注入webView了,

       let userScript = WKUserScript(source: source,
                                      injectionTime: .atDocumentEnd,
                                      forMainFrameOnly: true)

        let userContentController = WKUserContentController()
        userContentController.addUserScript(userScript)

        let configuration = WKWebViewConfiguration()
        configuration.userContentController = userContentController

        self.webView = WKWebView(frame: self.documentDiscriptionView.bounds,
                                 configuration: configuration)
        self.webView.navigationDelegate = self
        self.webView.scrollView.isScrollEnabled = false
        self.webView.scrollView.bounces = false

        self.webView.isOpaque = false
        self.webView.backgroundColor = UIColor.clear
        self.webView.scrollView.backgroundColor = UIColor.clear

        self.self.webViewContainerView.addSubview( self.webView)
  1. 我已经在“重写功能viewDidAppear(_动画:Bool)” 方法中添加了以上所有代码,只需复制并粘贴代码,即可使用。

有关详细信息,请参见Detail Answer

希望此解决方案对某人有所帮助,请让我知道是否需要其他详细信息,我们将竭诚为您服务。

答案 2 :(得分:0)

您可以将html预加载为字符串,将本地CSS的内容注入一些样式标签中,最后在WKWebView中显示修改后的字符串。

在下面,您将看到一个可行的解决方案,您只需要在项目内部拖动一个名为inject.css的文件即可。该文件包含您要应用的样式。

请确保您有一个名为webView的WKWebView,并且有一个连接到插座的按钮以使以下解决方案有效(该解决方案可能需要重构):

import UIKit
import WebKit

class ViewController: UIViewController {
  @IBOutlet weak var webView: WKWebView!

  @IBAction func loadStuffTapped(_ sender: Any) {

    injectCssAndShow(url: "https://www.wikipedia.org/")

  }

  // this one loads the css from your bundle
  func loadCss()->String? {
    if let filepath = Bundle.main.path(forResource: "inject", ofType: "css") {
      do {
        let contents = try String(contentsOfFile: filepath)
        print(contents)
        return contents
      } catch {
        // contents could not be loaded
      }
    } else {
      // inject.css not found!
    }
    return nil
  }

// this (kind of bloated...) function loads the orignal html, injects your css and shows the modified version inside of your WKWebview
  func injectCssAndShow(url: String) {

    let request = NSMutableURLRequest(url: NSURL(string: url)! as URL,
                                      cachePolicy: .useProtocolCachePolicy,
                                      timeoutInterval: 10.0)
    request.httpMethod = "GET"

    let session = URLSession.shared
    let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
      if (error != nil) {
        print(error as Any)
      } else {
        let htmlString = String(decoding: data ?? Data(), as: UTF8.self)

        DispatchQueue.main.async {

          let result = htmlString.range(of: "<title>",
                                        options: NSString.CompareOptions.literal,
                                        range: htmlString.startIndex..<htmlString.endIndex,
                                        locale: nil)

          if let range = result {
            let start = range.lowerBound
            let injection = self.loadCss() ?? ""
            let modifiedHtml = "\(htmlString[htmlString.startIndex..<start]) <style>\(injection)</style> \(htmlString[start..<htmlString.endIndex])"
            self.webView.loadHTMLString(modifiedHtml, baseURL: URL.init(string: url))
          }
        }
      }
    })

    dataTask.resume()

  }
}

Animation of posted solution