1

Trying to load HTML content that contains images into either a UITextView or a WKWebView (I just need it rendered!)

However, when I load HTML into WKWebView, the images do not load and the view doesn't reload and respect the Autolayout constraints from before the content loads:

enter image description here

Relevant code is here:

    webView.navigationDelegate = self
    webView.loadHTMLString(body, baseURL: nil)

and

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {

    if webView.isLoading == false {
        webView.evaluateJavaScript("document.body.scrollHeight", completionHandler: { [weak self] (result, error) in
            guard let safeSelf = self else {return}
            if let height = result as? CGFloat {
                print("height of webview: \(height)")
                webView.frame.size.height += height
                //Layout subviews?
            }
        })
    }

}

However, with UITextView, according to the accepted answer found here I can do the following:

extension String {

var htmlToAttributedString: NSMutableAttributedString? {
    guard let data = data(using: .unicode) else { return NSMutableAttributedString() }
    do {
        return try NSMutableAttributedString(data: data, options: [.documentType: NSMutableAttributedString.DocumentType.html], documentAttributes: nil)
    } catch {
        return NSMutableAttributedString()
    }
}

and set it as such:

textView.attributedText = htmlString.htmlToAttributedString

enter image description here

This works well in terms of the Autolayout... for just texts, but it is not preserving images(doesn't even show an indication of where images would go), only text. Not event preserving fonts or font sizes used by the html.

I have directly used the accepted answer from that post and it does not preserve images, even though the OP asked for preserving images.

What is either a) the correct way to load content into a WKWebView and load the images (my Transport Security is set to allow arbitrary loads for this demo) or b) preserve images in UITextView's parsing of the HTML? I am given the html directly and not the URL.

EDIT: For testing purposes, I have hardcoded a small sample html in my code for use in UIWebView / WKWebView to mirror a portion of what I get from the API call.

let body = "<div class=\"media-attachment\"><a href=\"https://www.hnmagazine.com/2017/11/07/latinx-really-mean/\"><img src=\"https://testimages.weareher.com/feed/0/2018-08/t9Qc549F7uCtZdbdXx1ERLbXJN2EXIXVacouJDlX.png\"/></a><p class=\"media-caption\">via <a href=\"https://latinxontherise.podbean.com/\">Latinxontherise</a></p></div></div>"
daredevil1234
  • 1,303
  • 1
  • 10
  • 34
  • If you have HTML but not a URL, is it from a local file? You need to have the images stored in your project and not in `xcassets`. – Chris Aug 08 '18 at 19:37
  • @Chris this medium article gives a demo that loads an image but doesn't need the image stored locally. View the image demo in the comments by the OP. https://medium.com/swift2go/swift-how-to-convert-html-using-nsattributedstring-8c6ffeb7046f – daredevil1234 Aug 08 '18 at 19:42
  • Possible alternative: https://stackoverflow.com/questions/24010035/how-to-add-image-and-text-in-uitextview-in-ios – ekscrypto Aug 09 '18 at 03:15

2 Answers2

0

i suggest u should UIWebView to load HTMLString. Remember drag delegate for webView and u only call: your_webview.loadHTMLString(yourHTMLString, baseURL: nil) your_webview.scalesPageToFit = true

anhvd.fiwi
  • 1
  • 1
  • 3
  • UIWebview is deprecated in favor of WKWebview. Support for UIWebview is gonna be dropping after iOS 12 – daredevil1234 Aug 09 '18 at 16:18
  • i don’t know this infomation, but i just seen the problem that like your problem, after i used UIwebview, all of them resolved :) – anhvd.fiwi Aug 09 '18 at 16:24
  • Just tried UIwebview, height renders well and follows auto layout but still not loading images? The image urls work fine in my browser or if I load it elsewhere in the application – daredevil1234 Aug 09 '18 at 16:59
  • can u sent me your stringHTML? – anhvd.fiwi Aug 10 '18 at 00:06
  • see edit. Added portion of the html i am trying to load that includes one of the images – daredevil1234 Aug 10 '18 at 00:24
  • i tried your url and detected problem at image url. I tried your HTMLString with diffrent image url "http://demoapp.comicola.com/wp-content/uploads/2018/08/bia-chie-vukhuchuyetphung-ngang-300x225.jpg". Image loaded. – anhvd.fiwi Aug 10 '18 at 07:25
  • your HTMLString with diffrent image: "" – anhvd.fiwi Aug 10 '18 at 07:28
  • I see that your demo image works. Could you explain what I need to do differently with the URL for the images to load correctly? It is weird to me because they load correctly for Android but not iOS, hence I thought it was an iOS client issue. I even tried other images from other websites before and they hadn't worked. Could you submit it as an answer as well? So i can accept it once i verify – daredevil1234 Aug 10 '18 at 16:25
0

So, the images were not loading because they were webP images, and Apple does not support webP (because it is a google thing).

As for the auto layout stuff, here is the basic solution (for the WKWebView):

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {

    //A delay here is needed because didFinish does not guarantee content has finished displaying
    //Height can only be retrieve after display finishes - hence the delay.
    var height: CGFloat = 0.0
    dispatch_after(0.1, block: {
        height = webView.scrollView.contentSize.height

        webView.snp.makeConstraints({make in //I used SnapKit here, because that's how my repo is setup
            make.height.equalTo(height)
        })
        // If the the webview is in another view, update that view's frame with the height + the existing height of that view's frame.  For me, I had the webview as the header of a uitableview (the cells are user comments, where the header is the "post"):
        guard var headerFrame = self.tableView.tableHeaderView?.frame else {return}
        headerFrame.size.height = headerFrame.size.height + height
        self.header.frame = headerFrame
        self.tableView.tableHeaderView = self.header
    })

The above code is working very reliably for me. The only only things that i needed was to use WKPreferences to set a minimum font, since the WKWebview doesn't respect the font existing in the html, and disabled scrolling, because that is the point of resizing it to match the content.

daredevil1234
  • 1,303
  • 1
  • 10
  • 34