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.
Related
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:
Using swift3 with xcode8
Below is my viewconroller.swift
class ViewController: UIViewController {
#IBOutlet weak var YahooWebview: UIWebView!
#IBOutlet weak var activity: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
let YURL = URL(string: "http://www.yahoo.com")
let YURLRequest = URLRequest(url: YURL!)
YahooWebview.loadRequest(YURLRequest)
}
}
func webViewDidStartLoad(YahooWebview: UIWebView) {
activity.startAnimating()
}
func webViewDidFinishLoad(YahooWebview: UIWebView) {
print("show indicator")
activity.stopAnimating()
}
Why my indicator is not showing when webview is loading?
I can not even see string "show indicator" from my log in Xcode.
You need to set your class as the delegate of UIWebView as
YahooWebview.delegate = self
Check my answer to get details regarding delegates and delegation pattern.
Note from apple developer: In apps that run in iOS 8 and later, use the
WKWebView class instead of using UIWebView. Additionally, consider setting the WKPreferences property javaScriptEnabled to false if you render files that are not supposed to run JavaScript.
There can be two problems as mentioned in comments.
Both can be solved in your Stroyboard/xib file.
Your UIActivityIndicatorView is may be hidden behind UIWebView. Just change the position of the view so that it comes above in the view heirarchy.
You may not have set delegate property of UIWebview class as your ViewController. Right click on webview and check. This needs to be set as you are animating the activity indicator view inside delegate methods.
I have made a baseViewController which is derived from UIViewController, SlideMenuDelegate and UIWebViewDelegate
Then I have created subclass which are derived from baseviewcontroller
LoginVC - displays login screen
PlayVC - shows a webview if login is successful.
Everything is fine except that webview is not scrolling at all.
I have tried everything suggested in all posts so far regarding scrolling
Below is my code written in PlayVC.swift
#IBOutlet weak var web1: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
addSlideMenuButton()
let webUrl : URL = URL(string: "http://brainyknights.com")!
let webRequest : URLRequest = URLRequest(url: webUrl)
web1.scalesPageToFit = true
web1.isUserInteractionEnabled = true
web1.scrollView.isScrollEnabled = true
web1.loadRequest(webRequest)
// Do any additional setup after loading the view.
}
remove this line web1.scalesPageToFit = true
#IBOutlet weak var web1: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
addSlideMenuButton()
let webUrl : URL = URL(string: "http://brainyknights.com")!
let webRequest : URLRequest = URLRequest(url: webUrl)
//web1.scalesPageToFit = true
web1.isUserInteractionEnabled = true
web1.scrollView.isScrollEnabled = true
web1.loadRequest(webRequest)
// Do any additional setup after loading the view.
}
According Apple Documentation
scalesPageToFit
A Boolean value determining whether the webpage scales to fit the view
and the user can change the scale.
if web1.scalesPageToFit is true then the web content will fit in your UIWebView frame and the contentSize will have the same height and width as your UIWebViewframe making imposible to be scrollable
so remove this line and must work
web1.scalesPageToFit = true
I hope this helps you
I have a webView in a simple application which is under a UIImageView. I intend on displaying the UIImageView until webView loads some data and fires a method in the web view delegate. Webview loads the data, delegate method is called fine. However, I am having trouble manipulating other views like the UIImageView.
Here is my code;
class ViewController: UIViewController,UIWebViewDelegate {
//contains the imageView and activityWorkingIndicator
#IBOutlet weak var splash_view: UIView!
#IBOutlet var contentWebView: UIWebView!
//Contains the Webview and other views to be displayed after the splash his hidden
#IBOutlet weak var splash_view_not: UIView!
override func viewWillAppear(animated: Bool)
{
contentWebView?.scrollView.bounces = false;
contentWebView?.delegate = self
let url = NSURL(string: "http://localhost/something/");
let request = NSURLRequest(URL: url!);
contentWebView?.loadRequest(request);
}
....
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if let scheme = request.URL?.scheme {
if scheme == "myRequestScheme"{
let task : String = (request.URL?.host)!;
switch task {
case "systemReady":
print("checkpoint 1");//works fine
splash_view?.hidden = true;//no effect at all
splash_view_not?.hidden = false;//no effect at all
print("checkpoint 2");//works fine
break;
default:
break
}
}
}
return true;
}
}
What am I missing here?
It looks like you are using Auto Layout. If that is the case, using .hidden has more implications than you think. If you are calling it in a method after the view has already been loaded, you need to work with constraints instead of hidden. Some people create constraint outlets and set them to active to hide things. Some people set alphas and bring subviews to front to hide things, etc.
I believe this is the preferred way:
http://candycode.io/hiding-views-with-auto-layout/
And here is a stack overflow thread with A LOT of information on your best options to hide things with AutoLayout:
AutoLayout with hidden UIViews?
You should hide or show any control in delegate method on main thread.
Use like this
DispatchQueue.main.async {
splash_view_not?.hidden = false
}
I have two ViewControllers, which I am trying to pass a NSURLRequest through a delegate.
Here is the delegate:
protocol URLRequestDelegate{
func urlRequest(url: NSURLRequest)
}
The delegate is successfully passing the NSURLRequest, because I have error checked it.
However in the ViewController the delegate is passing the NSURLRequest to, I have implemented the required function to conform to the protocol which is where I use the function webView.loadRequest() to load the webView with the desired webpage.
The webView is done through code and not storyboard:
var webView: UIWebView = UIWebView(frame: CGRect(x: 0, y: 0, width: UIScreen.mainScreen().bounds.width, height: UIScreen.mainScreen().bounds.height))
Here is that function:
func urlRequest(url: NSURLRequest) {
//Load URL from the delegate.
webView.loadRequest(url)
}
But this does't load the UIWebView with the NSURLRequest passed in the delegate, I am thinking that the delegate method func urlRequest() isn't calling correctly or maybe before viewDidLoad() method.
I have even set the self.view.webView.delegate = selfand implemented the UIWebViewDelegate on this class and implemented the func viewDidStartLoad() & fun viewDidFinishLoad with println() inside them to check to see if the codes being run when I call webView.loadRequest(url) however they never seem to be printed of.
So this leaves me puzzled, because I'm not quite sure what is causing the .loadRequest() not to function correctly within the delegate method func urlRequest().
I do know that if I put .loadRequest() within viewDidLoad() with lets say a hardcoded url of http://www.google.com it does work. However I can't pass the delegates NSURLRequest within viewDidLoad() as it has to be implemented inside func urlRequest() to conform correctly to the protocol.
Did you make sure to set the delegate for your first ViewController? You first ViewController needs to have a property of type URLRequestDelegate and you need to set that property equal to your second ViewController at some point.