I am having trouble resolving an odd issue with my webView. I am attempting to load a web page (any web page) in a webView which is the sole object within a UIViewController. When I create an instance of the view controller and push it onto the stack, the screen is blank and white. For now I am attempting to load www.apple.com. Here is the relevant code:
UIViewController:
import UIKit
class GoodReadsVC: UIViewController {
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL (string: "http://www.apple.com")
let requestObj = NSURLRequest(URL: url!)
webView?.loadRequest(requestObj);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
For what it is worth, I know that the webView is indeed connected to the xib, due to the little dot being filled in the left margin.
Pushing the controller onto the nav stack:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let bookWebView = GoodReadsVC(nibName: "GoodReadsVC", bundle: NSBundle.mainBundle())
self.navigationController!.pushViewController(bookWebView, animated: true)
tableView.reloadData()
}
What am I doing wrong?
This was a case of the loading being blocked by this error:
Transport security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
The solution to this problem may be found here:
Transport security has blocked a cleartext HTTP
Related
In a UIWebview I want to change
<iframe src=“//player.vimeo.com/video/164231311?autoplay=1” width=“700" height=“394” frameborder=“0" webkitallowfullscreen=“” mozallowfullscreen=“” allowfullscreen=“”></iframe>
to
<iframe src=“//player.vimeo.com/video/164231311" width=“700” height=“394" frameborder=“0” webkitallowfullscreen=“” mozallowfullscreen=“” allowfullscreen=“”></iframe>
since I want the user to be presented with a play button instead of a pause button since autoplay is not allowed on iOS. It'll be more natural for the user to see a play button directly instead of the pause button as in the image below.
How do I do that in a simple way? I’ve tried some stuff like
webView.stringByEvaluatingJavaScript(from:“document.getElementsByTagName(…)
without success so far.
Here I made rough demo code to solve your issue. Put your logic with that and it will solve your issue.
It was tested and had seems working perfectly.
import UIKit
class ViewController: UIViewController,UIWebViewDelegate {
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
webView.loadRequest(URLRequest(url: URL(string: "file:///Users/user/Downloads/index.html")!))
// 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.
}
func webViewDidFinishLoad(_ webView: UIWebView) {
// get your current iframe src value
let iframeSrcValue:String = webView.stringByEvaluatingJavaScript(from: "document.getElementsByTagName('iframe')[0].src")!
// Here is your current value with AutoPlay
print(iframeSrcValue)
//Create new URL without Auto Play
let modifiedSrcValue = "https://www.youtube.com/embed/td8pYyuCIIs"
// Apply it to webview
let evaluate: String = "document.getElementsByTagName('iframe')[0].src='\(modifiedSrcValue)';"
webView.stringByEvaluatingJavaScript(from: evaluate)
}
}
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 the following code for a view which is one of the options attached to a tab on a Tab Bar Controller (swift 3):
import UIKit
class SecondViewController: UIViewController {
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let str8REDURL = URL(string: "https://str8red.com/leaderboard/")
let str8REDURLRequest = URLRequest(url: str8REDURL!)
webView.loadRequest(str8REDURLRequest)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
This is working perfectly. However, the user can currently have a browse of the site and then select another tab. When they select this tab I would like the webView to reload the URL as above, so basically resetting that view as if it had just loaded. I am assuming there is some "reload" option but can't seem to work it out and would appreciate any guidance.
UPDATE
After a few suggestions I even tried the following with no joy:
func viewWillAppear() {
let str8REDURL = URL(string: "https://str8red.com/leaderboard/")
let str8REDURLRequest = URLRequest(url: str8REDURL!)
webView.loadRequest(str8REDURLRequest)
}
Many thanks, Alan.
Just put the load request in viewWillAppear(), it will be called everytime you change the tab back to that screen
webview.loadRequest() will load the webview content. webview.reload() reloads the last request which has finished loading. Therefore for your case, you can use webview.reload()
Currently i got a small problem with WebViews that dont release there memory usage in time, i m calling some webviews (the user can open them switch back to a map (via Tabbar) and open a new one),
Everytime a WebView is called it use up to 30MB RAM, so after 10 WebViews the App runs into a memory warning, so i m looking for a way (as i found in other Posts there is no way caus it handled automatic) to release the memory after switching back to the map from the webview.
This is how i call my WebView
import UIKit
class ViewController_webView: UIViewController {
/* ################################################## IBOutlets ################################################## */
#IBOutlet weak var webView: UIWebView!
#IBOutlet weak var TBB_shop: UITabBarItem!
#IBOutlet weak var activity: UIActivityIndicatorView!
/* ################################################## Home Button ################################################## */
#IBAction func BThome(sender: AnyObject) {
var shopurl = "http://google.com"
let webviewURL = NSURL(string: shopurl)
let request = NSURLRequest(URL: webviewURL)
webView.loadRequest(request)
}
/* ################################################## ViewDidLoad ################################################## */
override func viewDidLoad() {
super.viewDidLoad()
var TBB_shop_img = UIImage(named: "TabbarShopping.png") as UIImage
TBB_shop.selectedImage = TBB_shop_img
}
/* ################################################## MemoryWarning ################################################## */
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
println("Memory Warning")
}
/* ################################################## viewWillAppear ################################################## */
override func viewWillAppear(animated: Bool) {
var shopurl = "http://google.com"
let webviewURL = NSURL(string: shopurl)
let request = NSURLRequest(URL: webviewURL)
webView.loadRequest(request)
}
/* ################################################## Activity Indicator ################################################## */
func webViewDidStartLoad(_ : UIWebView){activity.startAnimating()}
func webViewDidFinishLoad(_ : UIWebView){activity.stopAnimating()}
}
Is there anyway to use the
override func viewDidDisappear(animated: Bool) {
<#code#>
}
to release the memory usage of a webview? Or anyway to reduce the usage of memory?
From your code I deduce that the webView is in a nib.
To reduce the memory footprint, you might want to try creating and removing the webView in viewWillAppear and viewWillDisappear, respectively.
This would mean that you might have to re-load the content if the user were to go back to it. Annoying from the user perspective.
Releasing memory can depend on how you are bringing up the view - here is a modal presentation of a view controller - this will not release memory of a previously loaded view controller:
let vc = self.storyboard!.instantiateViewControllerWithIdentifier("WebViewController") as WebViewController
let navigationController = UINavigationController(rootViewController: vc)!
self.presentViewController( navigationController, animated: true, completion: nil)
Below is a case where the rootViewController is replaced with the new controller - in this case the rootViewController value is changed - so the original view controller (if one was loaded before) reference count goes down to 0 and should be removed from memory, in theory:
let vc = self.storyboard!.instantiateViewControllerWithIdentifier("WebViewController") as WebViewController
let navigationController = UINavigationController(rootViewController: vc)!
let window = UIApplication.sharedApplication().windows[0] as UIWindow
window.rootViewController = navigationController
I tried the latter case in a code situation like what is described in the question. I saw an improvement in memory releasing, however I have to admit that the memory did not go back where I started from - don't know why. I hope somebody has a better solution.
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.