Change webview height based on html text using autolayot in ios swift - ios

created a webview which loads html text.
var html_string = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
self.webView.loadHTMLString(html_string, baseURL: nil)
i want set webview height to its content.without scrolling in the webView

Mind that the component is WKWebView, Webview is a thing of the past.
Try this function:
func webViewDidFinishLoad(_ webView: UIWebView) {
webView.frame.size.height = 1
webView.frame.size = webView.sizeThatFits(.zero)
webView.scrollView.isScrollEnabled=false;
myWebViewHeightConstraint.constant = webView.scrollView.contentSize.height
webView.scalesPageToFit = true
}
Remember to create an outlet for myWebViewHeightConstraint and updateConstrain as well.
You have a nice day!

Use following code for this, I hope this helps you.
Note:- 'UIWebView' was deprecated in iOS 12.0: No longer supported, So please use WKWebView instead of UIWebView
For UIWebView
func webViewDidFinishLoad(_ webView: UIWebView) {
webView.frame.size.height = 1
webView.frame.size = webView.sizeThatFits(.zero)
webView.scrollView.isScrollEnabled=false;
myWebViewHeightConstraint.constant = webView.scrollView.contentSize.height
webView.scalesPageToFit = true
}
For WKWebView
If you want to use WKWebView then you need to do the following things.
1) import WebKit
2) make your ViewController inherit from WKNavigationDelegate
3) hook up the WKWebView’s delegate: webView.navigationDelegate = self
4) implement the following protocol function:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.frame.size.height = 1
webView.frame.size = webView.scrollView.contentSize
}

Related

How to make transparent background WKWebView in Swift

I want a transparent web page in swift, so I have tried the below code according to this answer. Still, I am not getting a transparent web page. nothing changes in webview colour.. may I know why??
where am I going wrong? please help me in below code.
Total code:
import UIKit
import WebKit
class WebviewViewController: UIViewController {
#IBOutlet weak var testWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
guard let url = URL(string: "https://developer.apple.com/swift/") else { return }
let request = URLRequest(url: url)
testWebView.load(request)
// Do any additional setup after loading the view.
self.testWebView = WKWebView()
self.testWebView!.isOpaque = false
self.testWebView!.backgroundColor = UIColor.clear
self.testWebView!.scrollView.backgroundColor = UIColor.clear
}
}
Please help me with the code.
the code to make transparent background is as follow what you already added.
self.testWebView!.backgroundColor = UIColor.clear
now question is you added right code already then why you are not getting reliable output ..?
Also , if you try
self.testWebView!.alpha with any value, it will affect all of WebPages as WkWebView is a single view and changing it's alpha will also affect the components within...
it happened because the page you load in WebViewController has some HTML and CSS code, you make your WebViewController transparent but because of that HTML &CSS you can't see it's transparency as each webpage has it's own background color settings (which is merely impossible to change for each webpage)
I hope you will understand and it will help you ...:)
as I see, you use storyboard (#IBOutlet) and you can use Storyboard for setting your WKWebView:
And about code. This is enough for the result. You shouldn't set again self.testWebView = WKWebView(), because you use storyboard and you can set isOpaque with storyboard. As result:
class ViewController: UIViewController, WKNavigationDelegate {
#IBOutlet var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
webView.navigationDelegate = self
let url = URL(string: "https://developer.apple.com/swift/")!
webView.load(URLRequest(url: url))
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
let js = "(function() { document.body.style.background='transparent'; })();"
webView.evaluateJavaScript(js) { (_, error) in
print(error)
}
}
}
and evaluateJavaScript helped to add transparency for background:

WKWebView weird scroll behavior when long press to select text if contentInset is set

I am having an issue that long press and selecting text on the WKWebView will randomly scroll the web view. This behavior happens when I set the contentInset.top property of the scroll view of the web view.
[Screenshot]
Long press on the text. The green area is a native UIView https://ibb.co/P4LqgBB
After dragging on the text, WKWebView scrolls itself down unexpectedly https://ibb.co/r5KR4JB
Since my application need to show the native view above the web view potion, this behavior really frustrates my users when they need to copy and paste text from the web view.
Below is the minimum code that you can use to reproduce the issue. I tried this on iPhone 8 iOS 12.2 using Xcode 10.2. The issue occurs when webView.scrollView.contentInset.top = 100 is set. Moreover, if you change the value to something like 1000, where the contentInset.top is longer than the phone's screen size, long press will cause the web view to scroll instantly.
override func viewDidLoad() {
super.viewDidLoad()
// Create WKWebView
let webView = WKWebView(frame: .zero)
webView.translatesAutoresizingMaskIntoConstraints = false
webView.scrollView.contentInsetAdjustmentBehavior = .never
webView.clipsToBounds = false
webView.scrollView.bounces = false
// Create Native UIView
let nativeView = UIView(frame: .zero)
nativeView.translatesAutoresizingMaskIntoConstraints = false
nativeView.backgroundColor = .green
// Add WebView to the view
view.addSubview(webView)
webView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
webView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
webView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
webView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
// Set contentInset to give blank space for native view
webView.scrollView.contentInset.top = 100
// Add the native view as webView scrollView's child
webView.scrollView.addSubview(nativeView)
nativeView.leadingAnchor.constraint(equalTo: webView.leadingAnchor).isActive = true
nativeView.trailingAnchor.constraint(equalTo: webView.trailingAnchor).isActive = true
nativeView.topAnchor.constraint(equalTo: webView.scrollView.topAnchor,
constant: -100).isActive = true
nativeView.heightAnchor.constraint(equalToConstant: 100).isActive = true
// Load the webpage
let url = URL(string: "https://www.apple.com")!
let request = URLRequest(url: url)
webView.load(request)
}
I expect the long press and scroll behave like when contentInset.top is not set.
Does anyone know how to fix this issue?
Please add first UIScrollViewDelegate,WKNavigationDelegate,WKUIDelegate delegates in your viewcontroller and add below delegates.
// MARK: - WKWebView Delegate
private func webView(webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) {
print(error.localizedDescription)
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
// print("Strat to load")
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
// print("finish to load")
let javascriptStyle = "var css = '*{-webkit-touch-callout:none;-webkit-user-select:none}'; var head = document.head || document.getElementsByTagName('head')[0]; var style = document.createElement('style'); style.type = 'text/css'; style.appendChild(document.createTextNode(css)); head.appendChild(style);"
webView.evaluateJavaScript(javascriptStyle, completionHandler: nil)
}
// MARK: - UIScrollViewDelegate
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return nil
}
I have faced same issue and above code working fine for me. Hope it will help to you. #Chui
WKWebView creates a-lot of problems if the css isn't done clean enough.
I sugest moving back to UIWebView, it should fix all your problems

WKWebView, scrolling the web page to top

I tried this, which should work but doesn't:
webView.scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
I am working on a browser and have a couple of webViews in kept in stack. Some sites work as expected, start at the top, some do not.
Starts at top: http://leagueoflegends.com/
This one starts a little down, have to manually scroll up: http://euw.leagueoflegends.com/
Extra note, this problem never happens to the first webView. Even if I load the 2nd link and show it as first webView, it doesn't scroll to the middle.
I had a very similar problem when rotating my WKWebView.
After rotation to landscape the view is automatically scrolled to the middle.
I use following workaround to scroll to the top of the page again after rotation:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animate(alongsideTransition: nil, completion: { (context) in
self.webKitView.evaluateJavaScript("window.scrollTo(0,0)", completionHandler: nil)
})
}
In your case it should work to call this directly after you load your URL.
webKitView.evaluateJavaScript("window.scrollTo(0,0)", completionHandler: nil)
Or if your problem occurs when navigating within the WKWebView, you could use a WKNavigationDelegate (I have not tested this) :
override func viewDidLoad() {
super.viewDidLoad()
// load content of webKitView here and set as view or add as subview
webKitView.navigationDelegate = self
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webKitView.evaluateJavaScript("window.scrollTo(0,0)", completionHandler: nil)
}
Our app uses multiple WKWebView instances and we have also experienced this problem of some pages randomly scrolling to some location down the page.
We were able to work around the problem by having the next webView which will be loading the next page attached to the window hierarchy before loading the URL.
WKWebView* nextWebView = [WKWebView new];
[[[UIApplication sharedApplication] keyWindow] addSubview:webView.view];
[[[UIApplication sharedApplication] keyWindow] sendSubviewToBack:webView.view];
Then when you load your URL:
[nextWebView.view removeFromSuperview];
[controller.view addSubview: nextWebView.view];
I encountered this too. Finally, I fixed this way:
if #available(iOS 11, *) {
webView.scrollView.contentInsetAdjustmentBehavior = .never
}
If you have this issue on iOS 11, try this.
Before iOS 11.0, UIWebView was avilable with delegates to indicate that loading of webView is finished and we can do any operation after loading has been finished.
Now we have WKWebView which doesn't provide any delegate method to notify once your webView has finished loading. Due to this if we do following piece of code then it will not work:
let myURL = URL(string: "https://www.google.com")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
webView.scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
In this case, webView.load() is a asynchronous function which gets called and code moves further without waiting for its completion. Due to this your call for setContentOffset work but after that when webView finish loading it reset the ContentOffset to default, which is actually (0,0) but I am not sure why your WebView doesn't load from top. But doing code in following manner will may help you:
Extend to WKNavigationDelegate and implement didFinish navigation method in your ViewController and call setContentOffset in that method.
class ViewController: UIViewController, WKNavigationDelegate {
override func viewDidLoad() {
let myURL = URL(string: "https://www.google.com")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
webView.navigationDelegate = self
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
}
}
I would try to use javascript doc for scrolling to top:
NSString *script = #"window.scrollTo(0, 0)";
// UIWebView
// [webView stringByEvaluatingJavaScriptFromString:script];
// WKWebView
[webView evaluateJavaScript:script completionHandler:NULL];
Swift 4
This function is part of the WKWebView's UIScrollView and scrolls to a given rectangle.
scrollRectToVisible(_ rect: CGRect, animated: Bool)
A code example would look like:
let rect: CGRect = CGRect(x: 0, y: 0, width: 1, height: 1)
webView.scrollView.scrollRectToVisible(rect, animated: true)
This seems to happen if the WKWebView is not fully initialized or sized when asked to display a web page.
In my case, I created the web view during loadView in a UIViewController. If I then requested to navigate to a web page during viewDidLoad, the web view appeared scrolled partway down the page. I was able to fix the problem by moving the html request into viewWillAppear: (which is later in the view controller lifecycle).

Disable magnification gesture in WKWebView

I'm looking for a way to disable the "pinch to zoom" magnification gesture on the iOS implementation of WKWebView. There is a magnification BOOL property available for OS X but it doesn't seem to be available on iOS.
WKWebView.h
#if !TARGET_OS_IPHONE
/* #abstract A Boolean value indicating whether magnify gestures will
change the web view's magnification.
#discussion It is possible to set the magnification property even if
allowsMagnification is set to NO.
The default value is NO.
*/
#property (nonatomic) BOOL allowsMagnification;
I've, also, tried look at the WKWebView's gesture recognizers but that seems to be turning up an empty array. I'm assuming the actual recognizers are bured deeper in the component's structure (fairly complex, by the looks of it) and would rather not go digging for them if at all possible.
I know of possible hacks that could potentially disable the gesture from firing (selectively passing gestures to the WebView, add child view to capture pinch gesture, etc) but I've always found those introduce lag into the event and want to keep the implementation as clean/hack free as possible.
You can prevent your users from zooming by setting the delegate of your WKWebKit's UIScrollView and implementing viewForZooming(in:) as in the following:
class MyClass {
let webView = WKWebView()
init() {
super.init()
webView.scrollView.delegate = self
}
deinit() {
// Without this, it'll crash when your MyClass instance is deinit'd
webView.scrollView.delegate = nil
}
}
extension MyClass: UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return nil
}
}
I have tried setting minimumZoomScale and maximumZoomScale properties of UIScrollView to 1 or isMultipleTouchEnabled property of UIView to false or returning nil from invoking viewForZooming(in:) of UIScrollViewDelegate but none worked. In my case, after several trial and error, the following works in my case [Tested on iOS 10.3]:
class MyViewController: UIViewController {
var webView: WKWebView?
override viewDidLoad() {
super.viewDidLoad()
//...
self.webView.scrollView.delegate = self
//...
}
}
extension MyViewController: UIScrollViewDelegate {
func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
scrollView.pinchGestureRecognizer?.isEnabled = false
}
}
The below answer no longer works in iOS 10 beta.
To improve accessibility on websites in Safari, users can now
pinch-to-zoom even when a website sets user-scalable=no in the
viewport.
WKWebView seems to respect the viewport meta tag the same way Mobile Safari does (as to be expected). So, I found injecting that tag into the DOM through javascript after a page load does the trick. I would be weary of this solution unless you know exactly what HTML is being loaded into the webview, otherwise I suspect it would have unintended consequences. In my case, I'm loading HTML strings, so I can just add it to the HTML I ship with the app.
To do it generically for any webpage:
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
NSString *javascript = #"var meta = document.createElement('meta');meta.setAttribute('name', 'viewport');meta.setAttribute('content', 'width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no');document.getElementsByTagName('head')[0].appendChild(meta);";
[webView evaluateJavaScript:javascript completionHandler:nil];
}
It might be wise to take a look at what kind of navigation has just been completed, since only a new page will need this javascript executed.
Complete working code to disable zooming in WkWebView in Swift.
import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var webView : WKWebView!
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration:webConfiguration)
webView.uiDelegate = self
let source: String = "var meta = document.createElement('meta');" +
"meta.name = 'viewport';" +
"meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no';" +
"var head = document.getElementsByTagName('head')[0];" + "head.appendChild(meta);";
let script: WKUserScript = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
webView.configuration.userContentController.addUserScript(script)
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
let myUrl = URL(string: "https://www.google.com")
let myRequest = URLRequest(url: myUrl!)
webView.load(myRequest)
}
}
The native solutions were not working for me, and injecting JS is not ideal. I noticed that when a zoom occurs and my delegate is called, the pinchGestureRecognizer is enabled even though I disabled it when initializing the webview. To fix this, I set it to disabled whenever a zoom starts:
extension ViewController: UIScrollViewDelegate {
// disable zooming in webview
func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
scrollView.pinchGestureRecognizer?.isEnabled = false
}
}
Full Swift 3 / iOS 10 version of Landschaft's answer:
import UIKit
import WebKit
class MyViewController: UIViewController, UIScrollViewDelegate {
var webView = WKWebView()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(webView)
webView.scrollView.delegate = self
}
// Disable zooming in webView
func viewForZooming(in: UIScrollView) -> UIView? {
return nil
}
}
You can use UIScrollViewDelegate for this. First assign delegate to your webview in viewDidLoad() or any other suitable method as:
class LoginViewController: UIViewController, WKUIDelegate, UIScrollViewDelegate {
override func viewDidLoad() {
webView.scrollView.delegate = self
}
//Add this delegate method in your view controller
func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
scrollView.pinchGestureRecognizer?.isEnabled = false
}
}
In case you display a local html you could just modify this html and put this meta tag to your html:
<head>
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
</head>
A simple way to prevent zooming
override func viewDidLoad() {
super.viewDidLoad()
webView.scrollView.delegate = self
}
func scrollViewDidZoom(_ scrollView: UIScrollView) {
scrollView.setZoomScale(1.0, animated: false)
}
Swift 2.0
extension WKWebView {
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return nil
}
}
If it's not important for you to handle links inside html (say you want to display text only) the simplest would be to turn off user interaction
webView.userInteractionEnabled = false
this is how I disabled zoom for Swift3 view controller for one-webview-only app
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate, UIScrollViewDelegate {
#IBOutlet var webView: WKWebView!
override func loadView() {
webView = WKWebView()
webView.navigationDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
webView.scrollView.delegate = self
}
func viewForZooming(in: UIScrollView) -> UIView? {
return nil;
}
}
I don't have enough reputation to add comments to answers, but I wanted to mention that Kevin's solution (meta viewport) no longer works in iOS 10 beta. Landschaft's solution is working for me, though!
Since the JS solution uses W3C standards, it should always be supported.
Ah, Kevin, I wish that were how these things worked.
More here: https://stackoverflow.com/a/37859168/1389714
Disable double tap to zoom gesture by require failure of gesture recognizer. It will prevent the browser to take action when user double tap.
import UIKit
class DisableDoubleTapRecognizer : UITapGestureRecognizer, UIGestureRecognizerDelegate{
override init(target: Any?, action: Selector?) {
super.init(target: target, action: action)
}
init() {
super.init(target:nil, action: nil)
self.numberOfTapsRequired = 2;
self.delegate = self;
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true;
}
}
//in your view controller
override func viewDidLoad() {
super.viewDidLoad()
webView.addGestureRecognizer(DisableDoubleTapRecognizer())
}
Here's a slightly modified version of Gulshan Kumar's answer that worked for me in iOS 12.1.2, and it also prevents zooming due to double-taps and rotation. In my example, I just inject the script directly into the web view. I adjusted the scale to 60%, and there's no need to use concatenation in building up the source string.
let source = "var meta = document.createElement('meta'); meta.name = 'viewport'; meta.content = 'width=device-width, initial-scale=0.6, maximum-scale=0.6, user-scalable=no'; var head = document.getElementsByTagName('head')[0]; head.appendChild(meta);"
let script = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
webView.configuration.userContentController.addUserScript(script)
We need to change the delegate call with following signatures in XCode 8:
override func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return nil
}
The application I work on needed the view to be zoomed by Javascript. The accepted answer blocked zooming by JavaScript from inside the page too.
I only needed to disable pinch gesture by the user of the appliction. The only solution I've found is to disable the gesture of the web view after the page has loaded:
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
/* disable pinch gesture recognizer to allow zooming the web view by code but prevent zooming it by the user */
for (UIGestureRecognizer *gr in self.webView.scrollView.gestureRecognizers) {
if ([gr isKindOfClass:[UIPinchGestureRecognizer class]]) {
gr.enabled = NO;
}
}
}
If it is better to disbaled the Pinch zoom when the webpage finish loading, and it can also specify which particular URL is going to be disbaled
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
if let url = webView.url, url.absoluteString == "***" {
webView.scrollView.pinchGestureRecognizer?.isEnabled = false
}
print("finish")
}
For obj-c., add UIScrollViewDelegate protocol.
/* somewhere else, for example in viewDidLoad() */
_wkWeb.scrollView.delegate = self;
..
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view {
scrollView.pinchGestureRecognizer.enabled = NO;
}
This worked for me. https://gist.github.com/paulofierro/5b642dcde5ee9e86a130
let source: String = "var meta = document.createElement('meta');" +
"meta.name = 'viewport';" +
"meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no';" +
"var head = document.getElementsByTagName('head')[0];" + "head.appendChild(meta);";
let script: WKUserScript = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
let userContentController: WKUserContentController = WKUserContentController()
let conf = WKWebViewConfiguration()
conf.userContentController = userContentController
userContentController.addUserScript(script)
let webView = WKWebView(frame: CGRect.zero, configuration: conf)
If the webview is user for read-only purposes, i.e, just for displaying the web content use
webView.isUserInteractionEnabled = false
By this the zoom gesture won't work on it.

UIWebView webViewDidLoadFinish method not called

I've been playing around with web views in swift this evening, but have run into a bit of an issue.
For some reason I'm not able to get the webViewDidStartLoad or webViewDidFinishLoad methods to fire.
In my storyboard, I have an outlet called webView linked to my UIWebView element.
Is anyone able to help me with what I am doing wrong?
This is my viewController.swift file:
import UIKit
class ViewController: UIViewController, UIWebViewDelegate {
#IBOutlet var webView : UIWebView
var url = NSURL(string: "http://google.com")
override func viewDidLoad() {
super.viewDidLoad()
//load initial URL
var req = NSURLRequest(URL : url)
webView.loadRequest(req)
}
func webViewDidStartLoad(webView : UIWebView) {
//UIApplication.sharedApplication().networkActivityIndicatorVisible = true
println("AA")
}
func webViewDidFinishLoad(webView : UIWebView) {
//UIApplication.sharedApplication().networkActivityIndicatorVisible = false
println("BB")
}
}
Try this!
var req = NSURLRequest(URL: url)
webView.delegate = self
webView.loadRequest(req)
I experienced the same issue, even I did confirmed the UIWebViewDelete to self and implemented its methods.
//Document file url
var docUrl = NSURL(string: "https://www.google.co.in/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwjjwPSnoKfNAhXFRo8KHf6ACGYQFggbMAA&url=http%3A%2F%2Fwww.snee.com%2Fxml%2Fxslt%2Fsample.doc&usg=AFQjCNGG4FxPqcT8RXiIRHcLTu0yYDErdQ&sig2=ejeAlBgIZG5B6W-tS1VrQA&bvm=bv.124272578,d.c2I&cad=rja")
let req = NSURLRequest(URL: docUrl!)
webView.delegate = self
//here is the sole part
webView.scalesPageToFit = true
webView.contentMode = .ScaleAspectFit
webView.loadRequest(req)
above logic worked perfectly with test URl I got from quick google search.
But I when I replaced with mine. webViewDidFinishLoad never get called.
then How we solved?
On backed side we had to define content-type as document in headers. and it works like charm.
So please make sure on your server back-end side as well.
Here's my 2 cents battling with the same problem in SWIFT 3:
class HintViewController: UIViewController, UIWebViewDelegate
Declare the delegate methods this way (note the declaration of the arguments):
func webViewDidStartLoad(_ webView: UIWebView)
func webViewDidFinishLoad(_ webView: UIWebView)
Remember to set self to the webview's delegate property either in Interface Builder (Select the webview, drag from the delegate outlet to the webview from the Connections Inspector OR programmatically: self.webview.delegate = self)
As others noted, setting the delegate of UIWebView and conforming to the UIWebViewDelegate protocol is the best possible solution out there.
For other's who might make it here. I had put my delegate methods in a private extension which couldn't be accessed by the delegate caller. Once I changed the extension to internal the delegates started to get called properly.
There is my detailed solution for Swift 3:
1) in class declaration write the UIWebViewDelegate. For example:
class MyViewController: UIViewController, UIWebViewDelegate {
2) of course in storyboard make link to your UIViewController like this:
#IBOutlet weak var webView: UIWebView!
3) in the func viewDidLoad add one line:
self.webView.delegate = self
Nothing more. Special thinks to LinusGeffarth and LLIAJLbHOu for idea.

Resources