Last active
May 26, 2023 21:19
-
-
Save YoomamaFTW/333675c0f3a81f46023277ef7aa26217 to your computer and use it in GitHub Desktop.
WKWebView in a UIView for tableHeaderView that auto-resizes - Swift 5.1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import WebKit | |
// This gist assumes you already have a UITableView setup | |
// This gist is designed to look like Reddit's DetailViewController, HOWEVER | |
// The point of a WKWebView is that images can be loaded | |
// This gist is NOT perfect; look in comments for what needs to be fixed. | |
class ViewController: UIViewController, WKNavigationDelegate { | |
let headerView = UIView() | |
let titleView = UILabel() | |
let webView = WKWebView() | |
let tableView = UITableView() | |
override func viewDidLoad() { | |
setupTable() // The table is up for you to set up | |
setupTableHeader() // Where you will setup that header view | |
tableView.tableHeaderView = headerView | |
} | |
setupTableHeader() { | |
titleView.translatesAutoresizingMaskIntoConstraints = false | |
webView.translatesAutoresizingMaskIntoConstraints = false | |
webView.scrollView.bounces = false | |
webView.navigationDelegate = self | |
webView.loadHTMLString( | |
""" | |
<header><meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no'></header> | |
<b>HI THERE. HI THERE. HI THERE. HI THERE. HI THERE. HI THERE. HI THERE. HI THERE. HI THERE. HI THERE. </b> | |
<p>The above was just written to test the frame. I am hesitant to have add an img tag</p> | |
""", with: nil) | |
// IT IS VITAL THAT YOU HAVE THAT HEADER or else the document's frame isn't correct | |
webView.configuration.preferences.javaScriptEnabled = false // I have this for XSS or theft protection for users | |
headerView.addSubview(titleView) | |
headerView.addSubview(webView) | |
NSLayoutConstraint.activate([ // THERE IS AN ISSUE HERE with autolayout. I'm not an autolayout expert, so help needed | |
titleView.topAnchor.constraint(equalTo: headerView.topAnchor), | |
titleView.leadingAnchor.constraint(equalTo: headerView.leadingAnchor), | |
titleView.trailingAnchor.constraint(equalTo: headerView.trailingAnchor), | |
titleView.bottomAnchor.constraint(equalTo: webView.topAnchor), | |
webView.leadingAnchor.constraint(equalTo: headerView.leadingAnchor), | |
webView.trailingAnchor.constraint(equalTo: headerView.trailingAnchor), | |
webView.bottomAnchor.constraint(equalTo: headerView.bottomAnchor) | |
]) | |
} | |
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { | |
// I would like to incorporate this answer | |
// https://stackoverflow.com/a/41511422 | |
// It deals with images much better since gist this only works when initially loaded. But for images, it won't. | |
// This will resize the header view to accomodate for the new html. | |
// If you need animation design, then this is not the right function you should be using. | |
headerView.translatesAutoresizingMaskIntoConstraints = false | |
let widthConstraint = NSLayoutConstraint(item: headerView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: tableView.bounds.width) | |
headerView.addConstraint(widthConstraint) | |
webView.configuration.preferences.javaScriptEnabled = true | |
webView.evaluateJavaScript("document.readyState", completionHandler: { (complete, error) in | |
if complete != nil { | |
self.webView.evaluateJavaScript("document.body.scrollHeight", completionHandler: { (height1, error) in | |
let height = self.headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height + (height1 as! CGFloat) | |
self.headerView.frame.size.height = height | |
self.tableView.tableHeaderView = self.headerView | |
self.headerView.removeConstraint(widthConstraint) | |
self.headerView.translatesAutoresizingMaskIntoConstraints = true | |
self.webView.configuration.preferences.javaScriptEnabled = false | |
}) | |
} | |
}) | |
} | |
} | |
/* | |
This took me decades to figure out, but if you can make this more efficient, then here are the resources that helped me | |
that can help you figure out a better method. | |
How did I manage to get the WKWebView thing to work? Follow these links: | |
- Resizing the header view once the html loaded: https://gist.github.com/marcoarment/1105553afba6b4900c10#gistcomment-1933639 | |
- Getting scroll view size of WKWebView to add header view frame height: https://stackoverflow.com/questions/27515236/how-to-determine-the-content-size-of-a-wkwebview | |
- Making the font normal size since the viewport was wrong: https://stackoverflow.com/questions/45998220/the-font-looks-like-smaller-in-wkwebview-than-in-uiwebview | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This took me a couple days to figure out, but eventually I got a WKWebView inside of a tableHeaderView, not a UITableViewCell nor a section header view, but the table's header view. It incorporated a bunch of solutions that are shown at the bottom of the gist.
There are some things to fix though:
Recommendations: