Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load local web files & resources in WKWebView

Unlike with UIWebView and previous versions of WKWebView (iOS 10 & macOS 10.12), the default load operation for local files has moved from Bundle.main.path to Bundle.main.url. Similarly, loadFileURL has also become the default function to load local resources in WKWebView.

I know that .path and .url are entirely different and have both worked in the past – .path historically being the default-chosen method; however, it seems that the latest versions of Swift have broken most, if not all, .path solutions. The .path solutions seem to now flatten the directory hierarchy, putting all of the CSS, JS, and any other sub-directory contents, into one big directory. This causes loading errors when WKWebView attempts to load index.html, for example, with a linked, sub-folder stylesheet (ie. /css/style.css).

After seeing numerous questions and countless uncertain/broken answers to match, is there a quick and painless solution for implementing a WKWebView that can load local resources (including linked CSS/JS files), without any workarounds?

like image 575
Justin Bush Avatar asked Apr 03 '18 20:04

Justin Bush


People also ask

How do I import an HTML file into Wkwebview?

Once you have clicked "Add Files to", you will be prompted to select the files/folders that you want to add to your project. When you see the below dialog, make sure that you have selected the correct targets as well as "Copy items if needed" and "Create folder references" as you can see in the below image.

How do I open a local file in HTML?

HTML can be used to open a folder from our local storage. In order to open a folder from our local storage, use 'HREF' attribute of HTML. In the HREF attribute, we specify the path of our folder.

When you open a page locally the protocol is to open the file?

You need to use the file:/// protocol (yes, that's three slashes) if you want to link to local files. These will never open the file in your local applications automatically. That's for security reasons which I'll cover in the last section. If it opens, it will only ever open in the browser.


1 Answers

Updated for Swift 4, Xcode 9.3


This methods allows WKWebView to properly read your hierarchy of directories and sub-directories for linked CSS, JS and most other files. You do NOT need to change your HTML, CSS or JS code.

Solution (Quick)

  1. Add the web folder to your project (File > Add Files to Project)
    • Copy items if needed
    • Create folder references *
    • Add to targets (that are applicable)
  2. Add the following code to the viewDidLoad and personalize it to your needs:

    let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "website")! webView.loadFileURL(url, allowingReadAccessTo: url) let request = URLRequest(url: url) webView.load(request) 

Solution (In-Depth)

Step 1

Import the folder of local web files anywhere into your project. Make sure that you:

Xcode > File > Add Files to "Project"

☑️ Copy items if needed

☑️ Create folder references (not "Create groups")

☑️ Add to targets

Step 2

Go to the View Controller with the WKWebView and add the following code to the viewDidLoad method:

let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "website")! webView.loadFileURL(url, allowingReadAccessTo: url) let request = URLRequest(url: url) webView.load(request) 
  • index – the name of the file to load (without the .html extension)
  • website – the name of your web folder (index.html should be at the root of this directory)

Conclusion

The overall code should look something like this:

import UIKit import WebKit  class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {      @IBOutlet weak var webView: WKWebView!      override func viewDidLoad() {         super.viewDidLoad()          webView.uiDelegate = self         webView.navigationDelegate = self          let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "Website")!         webView.loadFileURL(url, allowingReadAccessTo: url)         let request = URLRequest(url: url)         webView.load(request)     }  } 

If any of you have further questions about this method or the code, I'll do my best to answer!

like image 105
Justin Bush Avatar answered Nov 04 '22 00:11

Justin Bush