Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
825 views
in Technique[技术] by (71.8m points)

ios - WKWebView fails to load images and CSS using loadHTMLString(_, baseURL:)

Apple's recommendation:

In apps that run in iOS 8 and later, use the WKWebView class instead of using UIWebView.

Thus, I have replaced my good old UIWebView with a shiny new WKWebView. But what I thought to be an easy exercise (simply swapping the classes and replacing the delegate methods) turned out to be a real mess.

The Problem

When I load an HTML string using

loadHTMLString(String, baseURL: URL?)

the web view loads and renders the pure HTML but it doesn't load any images or CSS files referenced inside the htmlString.

This happens only on a real device!
In Simultor all referenced resources are loaded correctly.

Simulator Real Device

Example

I have defined a simple htmlString in my view controller class:

let imageName = "image.png"

let libraryURL: URL // The default Library URL

var htmlString: String {
    return "<html> ... <img src="(imageName)" /> ... </html>"
    // "..." represents more valid HTML code incl. header and body tags
}

The image is stored in the root Library folder so its URL is:

let imageURL = libraryURL.appendingPathComponent(imageName)

Now I load the htmlString into the web view:

webView.loadHTMLString(htmlString, baseURL: libraryURL)

and it doesn't load the image even though the baseURL is set correctly.

Ideas for a Solution

  1. Maybe WKWebView has a problem with resolving relative paths so my first idea was to use absolute paths inside the HTML string instead.
    → ? Doesn't work.

  2. Two answers to another SO post suggested that using
    loadFileURL(URL, allowingReadAccessTo: URL)
    instead of loadHTMLString(...) works in iOS 9+.
    → ? That works.

However, I cannot use solution 2 because my HTML files are encrypted and the decrypted files must not be stored on the disk.

Question

Is there any way to load local resources like images and styles using the WKWebView's

loadHTMLString(String, baseURL: URL?)

function? Or is still a bug in iOS 9+?

(I just cannot believe that Apple provides and recommends using a web view that cannot load any local web content from inside an HTML string?!)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Without taking a look at your actual project it's difficult to give some hundreed percent sure advices.

However:

class ViewController: UIViewController {

    var webView = WKWebView()

    override func viewDidLoad() {
        super.viewDidLoad()
        webView.translatesAutoresizingMaskIntoConstraints = false
        let views = [
            "webView" : webView
        ]
        view.addSubview(webView)
        var constraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|[webView]|", options: [.AlignAllLeading, .AlignAllTrailing], metrics: nil, views: views)
        constraints.appendContentsOf(NSLayoutConstraint.constraintsWithVisualFormat("V:|[webView]|", options: [.AlignAllTop, .AlignAllBottom], metrics: nil, views: views))
        NSLayoutConstraint.activateConstraints(constraints)

        let path = NSBundle.mainBundle().pathForResource("ios - WKWebView fails to load images and CSS using loadHTMLString(_, baseURL_) - Stack Overflow", ofType: "htm")
        let url = NSURL(fileURLWithPath: path!)
        webView.loadHTMLString(try! String(contentsOfURL: url), baseURL: url.URLByDeletingLastPathComponent)

        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

I think the key point here is baseUrl parameter, you should setup it correctly. In my case i've used html's url without last path component - e.g. containing folder. This works fine on both device & simulator - check device snapshot. I've uploaded sample project to https://github.com/soxjke/WKWebViewTest so you can take a look (i've removed codesigning info from git)

Device snapshot

So, to recap - method is working, functionality is working, just you do something wrong with it. To help you get what's wrong with your solutions, i'll add some suggestions: 1. Remember, that simulator filesystem is case-insensitive, device filesystem is case-sensitive. So if you have your filenames in html in lowercase - this won't work on device. 8fFsD.png != 8ffsd.png 2. Remember, that when copying resources, XCode ignores your folder structure. So if your html has <img src="./img/1.png"> and your XCOde project has folder structure like

test.htm

img/

    1.png 
    2.png

After build it will be flattened, so test.htm and 1.png and 2.png will reside on same level

test.htm
1.png 
2.png

I'm almost sure, after you verify these two assumptions, you'll get this method working.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...