Webview and navigation controller - ios

I have a webview in my swift app with a bunch of links on the website it is connected to. When a link is pressed, how do I make it so instead of opening the link in the same view, make it open in a new view with a back button (navigation controller). My viewcontroller.swift code is below. Any help?
import UIKit
import Parse
import PKHUD
class Home: UIViewController {
#IBOutlet var homeweb: UIWebView!
#IBOutlet var HomeActivity: UIActivityIndicatorView!
var request: NSURLRequest? = NSURLRequest(URL: NSURL(string: "https://google.com")!)
override func viewDidLoad() {
super.viewDidLoad()
if navigationController?.viewControllers.count > 1 { navigationItem.leftBarButtonItem = nil }
PKHUD.sharedHUD.contentView = PKHUDSuccessView()
PKHUD.sharedHUD.show()
PKHUD.sharedHUD.dimsBackground.boolValue
PKHUD.sharedHUD.userInteractionOnUnderlyingViewsEnabled.boolValue
PKHUD.sharedHUD.hide(afterDelay: 3.0);
if let request = request {
homeweb.loadRequest(request)
}
}
}
extension Home: UIWebViewDelegate {
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if request != self.request && navigationType != .Other {
if let Home = storyboard?.instantiateViewControllerWithIdentifier("homeview") as? Home {
Home.request = request
navigationController?.pushViewController(Home, animated: true)
return false
}
}
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func webViewDidStartLoad(homeweb: UIWebView)
{
HomeActivity.startAnimating()
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
}
func webViewDidFinishLoad(homeweb: UIWebView)
{
HomeActivity.stopAnimating()
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
title = homeweb.stringByEvaluatingJavaScriptFromString("document.title")
}
#IBAction func about(sender: UIBarButtonItem) {
let alertController = UIAlertController(title: "About Ball00n", message: "Copyright ©2014-2015 GreenBalloon, LLC James Cozzi (jc0z) jamescozzi00#gmail.com balloonhack.webs.com", preferredStyle: .Alert)
let Action1 = UIAlertAction(title: "Close", style: UIAlertActionStyle.Default, handler: nil)
alertController.addAction(Action1)
self.presentViewController(alertController, animated: true, completion: nil)
}
}

set the viewcontroller to be the webview's delegate and implement the following method:
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
// check for your specific condition
if request.URL?.absoluteString == "some link" {
// push viewcontroller here or perform a segue
return false // to not follow the link in the webview
}
return true
}
now - after understanding what you really try to achieve :) - i did the following:
setup a viewcontroller in storyboard with just a webview all over the screen. ctrl drag from the webview to the webviewcontroller and set it to be its delegate. set the viewcontroller to a custom class "WebViewController". also set the storyboard ID to "WebViewController". drag from the webview to the WebViewController class and connect an IBOutlet called "webView". finally your WebViewController class should look like this:
import UIKit
class WebViewController: UIViewController {
#IBOutlet weak var webView: UIWebView!
var request: NSURLRequest? = NSURLRequest(URL: NSURL(string: "http://YOUR_INITIAL_WEBSITE")!)
override func viewDidLoad() {
super.viewDidLoad()
if navigationController?.viewControllers.count > 1 {
navigationItem.leftBarButtonItem = nil
}
if let request = request {
webView.loadRequest(request)
}
}
}
extension WebViewController: UIWebViewDelegate {
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if request != self.request && navigationType != .Other {
if let webViewController = storyboard?.instantiateViewControllerWithIdentifier("WebViewController") as? WebViewController {
webViewController.request = request
navigationController?.pushViewController(webViewController, animated: true)
return false
}
}
return true
}
func webViewDidFinishLoad(webView: UIWebView) {
title = webView.stringByEvaluatingJavaScriptFromString("document.title")
}
}
at least this is a start :)

Related

iOS Swift : can't Retrieve current url loaded in UIwebView

i am working in webview application iOS swift :
problem i am facing is i want to get each url which webview displays :
upon urls i have to perform some if else checks . but i could not get the urls which webview loads.
webview is displaying fine results and loading urls upon clicking . i want to fetch all urls which webview navigates on..
import Foundation
import UIKit
class seconVC: UIViewController {
var toPass:String!
var touser:String!
var toPassing:String!
#IBOutlet weak var webV: UIWebView!
#IBOutlet weak var L_back: UIBarButtonItem!
#IBOutlet weak var R_frwrd: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var domurl = toPass;
var username = touser;
var passwing = toPassing;
var sendurl = stringA+username+"/"+passwing;
//exchange login with auth/username/password
println(sendurl);
let url = NSURL (string: sendurl);
let requestObj = NSURLRequest(URL: url!);
webV.userInteractionEnabled = true
webV.loadRequest(requestObj);
}
#IBAction func L_back(sender: UIBarButtonItem) {
if (webV.canGoBack){
webV.goBack()
}
}
#IBAction func R_frwrd(sender: UIBarButtonItem) {
if (webV.canGoForward){
webV.goForward()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
all i want is to get string of current url and navigation buttons for webview :please help ? i referred all the internet no solution is working in my case .
There are couple of UIWebViewDelegate such as shouldStartLoadWithRequest or webViewDidStartLoad or webViewDidFinishLoad or didFailLoadWithError that help you to accomplish your goal. If you want to perform operation after view did finished then implement this delegate method
Swift 3
if let currentURL = webView.request?.url?.absoluteString{
print(currentURL)
}
as it mentioned here.
option-1
let currentURL = webV.request.URL.absoluteString
option-2
get URL in delegate method
func webViewDidFinishLoad(webView: UIWebView){
print(WebView.request?.mainDocumentURL)
}
option-3
func webViewDidFinishLoad(webView: UIWebView) {
let currentURL = webView.request().URL()
print("\(currentURL.description)")
}
or use like
func webViewDidFinishLoad(webView: UIWebView){
let currentURL = webView.request?.URL
}
option-4
func webViewDidFinishLoad(webView: UIWebView) {
let currentURL: = webView.stringByEvaluatingJavaScriptFromString("window.location.href")!
print("\(currentURL)")
}
option-5
func webView(webview: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
let currentURL = request.URL.absoluteString
print("\(currentURL)")
}
option-6
func webViewDidFinishLoad(WebVie: UIWebView) {
let currentURL = WebVie.request.mainDocumentURL
print("\(currentURL)")
}
First you have to define the delegate for WebView class. "WebView.delegate = self". Add this code beside one of the function above:
override func viewDidLoad() {
super.viewDidLoad()
myWebView.delegate = self }
and for exmaple:
func webViewDidFinishLoad(_ webView: UIWebView) {
if let currentURL = WebView.request?.url?.absoluteString{
print(currentURL)
}
}

iOS WebView - Open link in SFSafariViewController

So I am trying to detect a link click within a webView and then present this url in the new SFSafariViewController however am having some issues.
Anyone got any ideas?
This is what I am currently doing:
import UIKit
import SafariServices
class ViewController: UIViewController {
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let localfilePath = NSBundle.mainBundle().URLForResource("index", withExtension: "html");
let myRequest = NSURLRequest(URL: localfilePath!);
webView.loadRequest(myRequest);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadInView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) {
if (navigationType == UIWebViewNavigationType.LinkClicked){
let url = request.URL;
let sfViewController = SFSafariViewController(URL:url!, entersReaderIfAvailable: true)
self.presentViewController(sfViewController, animated: true, completion: { () -> Void in
print("May the force be with you!")
})
}
}
}

UIWebView and JavaScriptInterface in Swift

How can I to create the JavascriptInterface channel from my web site to my UIWebView?
Example in Android:
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
And from this JavascriptInterface I would like to draw the methods, as for example:
func webViewDidStartLoad(webView: UIWebView)
or
myActivityIndicator.startAnimating()
How can I do?
For WKWebView: source here
JavaScript
function callNativeApp () {
try {
webkit.messageHandlers.callbackHandler.postMessage("Hello from JavaScript");
} catch(err) {
console.log('The native context does not exist yet');
}
}
Swift
import WebKit
class ViewController: UIViewController, WKScriptMessageHandler {
#IBOutlet var containerView: UIView? = nil
var webView: WKWebView?
override func loadView() {
super.loadView()
let contentController = WKUserContentController()
contentController.addScriptMessageHandler(self, name: "callbackHandler")
let config = WKWebViewConfiguration()
config.userContentController = contentController
self.webView = WKWebView( frame: self.containerView!.bounds, configuration: config)
self.view = self.webView
}
override func viewDidLoad() {
super.viewDidLoad()
//I use the file html in local
let path = NSBundle.mainBundle().pathForResource("index", ofType: "html")
let url = NSURL(fileURLWithPath: path!)
let req = NSURLRequest(URL: url)
self.webView!.loadRequest(req)
}
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {// edit: changed fun to func
if (message.name == "callbackHandler"){
print("\(message.body)")
}
}
}
For UIWebView: source here
JavaScript in HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
(function(){
$(window).load(function(){
$('.clickMe').on('click', function(){
window.location = "foobar://fizz?Hello_from_javaScript";
});
});
})(jQuery);
</script>
Swift
import UIKit
class ViewController: UIViewController, UIWebViewDelegate {
#IBOutlet weak var Web: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let path = NSBundle.mainBundle().pathForResource("index", ofType: "html")
let url = NSURL(fileURLWithPath: path!)
let req = NSURLRequest(URL: url)
Web.delegate = self
Web.loadRequest(req)
}
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if request.URL?.query != nil {
print("\(request.URL!.query!)")
}
return true
}
}
Here's a quick example:
Register a URL Scheme such as foobar in Xcode
Handle this URL Scheme in your web view
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if request.URL?.query?.containsString("show_activity_indicator=true") {
myActivityIndicator.startAnimating()
}
}
Finally, call this from your JavaScript
// Show your activity indicator from JavaScript.
window.location = "foobar://fizz?show_activity_indicator=true"
Note: See my question here for more information on web view communication in iOS.

Back button not working for my manually loaded UIWebView for external website

Technologies: Swift, iOS8.1.3, XCode 6, Maverick
I've added a "rewind" back button to my UIWebview via the main.storyboard and connected it here on my view with a backButton func:
class ViewController: UIViewController, UIWebViewDelegate {
#IBOutlet weak var webView: UIWebView!
var detailItem: NSURL?
var grabData = false
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
self.navigationController?.toolbarHidden = false;
}
#IBAction func backButton(sender: AnyObject) {
self.webView.goBack()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if let url = self.detailItem {
webView.loadRequest(NSURLRequest(URL: url))
}
}
func webView(webView: UIWebView, shouldStartLoadWithRequest request:
NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if grabData {
grabData = false
return true
} else {
grabData = true
manuallyLoadPage(request)
return false
}
}
func manuallyLoadPage(request: NSURLRequest) {
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) {
(data, response, error) invar html = NSString(data: data, encoding: NSUTF8StringEncoding) as String
html = html.stringByReplacingOccurrencesOfString("</head>", withString: "<styles><link rel='stylesheet' type='text/css' href='link-to-styles.css' media='all'></styles></head>", options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil)
self.webView.loadHTMLString(html, baseURL: response.URL!)
}
task.resume()
}
My back button doesn't do anything when clicked and I want it to show the previous webpage. I think it has something to do with how I am intercepting the session and manually loading the WebView. Maybe it doesn't know what the original base url is? Something else?

webViewDelegate and function

I'm writing a small webBrowser in swift and when someone clicks a link inside a webView, this needs to be detected and the link is open in another view. I wanted to implement this by putting the code for the webView function inside a separate file, so that I will be able to use the function multiple times without copy pasting it. Thing is that the function does not get's called when someone clicks a link. Should I add something to the ViewController class or to the class for the webView function?
import Foundation
import UIKit
class myWebViewController: UIWebView {
let VC1 = ViewController(nibName: nil, bundle: nil)
let VC2 = secondViewController(nibName: nil, bundle: nil)
func webView(webView: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) -> Bool {
if(navigationType == UIWebViewNavigationType.LinkClicked){
var url = (request.URL)
currentURL=url
webView.stopLoading()
if(webView.accessibilityIdentifier == "second"){
VC2.performSegueWithIdentifier("first", sender: VC2)
}
else {
VC1.performSegueWithIdentifier("second", sender: VC1)
}
// self.delegate?.didReceiveAPIResults(jsonResult)
//
// with
//
// dispatch_sync(dispatch_get_main_queue())
// {
// self.delegate?.didReceiveAPIResults(jsonResult)
// }
}
return true
}
}
Here is a version using WKWebView and swift. It opens the clicked link in safari while the navigation works normally if you use the web address.
class AppDelegate: UIResponder, UIApplicationDelegate {
lazy var window: UIWindow = {
let window = UIWindow(frame: UIScreen.mainScreen().bounds)
window.backgroundColor = UIColor.whiteColor()
window.rootViewController = UINavigationController(rootViewController: ViewController())
return window
}()
func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
window.makeKeyAndVisible()
return true
}
}
class ViewController: UIViewController, WKNavigationDelegate, UITextFieldDelegate {
lazy var webView:WKWebView = {
let webView = WKWebView(frame: CGRectZero)
webView.navigationDelegate = self
return webView
}()
let textField: UITextField = {
let textField = UITextField(frame: CGRectMake(0, 6, 100, 30))
textField.clearButtonMode = .WhileEditing
textField.placeholder = "Enter your url here:"
return textField
}()
override func loadView() {
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
navigationItem.titleView = textField
}
func textFieldShouldReturn(textField: UITextField!) -> Bool {
if textField.isFirstResponder(){
textField.resignFirstResponder()
loadCurrentUrl()
}
return true
}
func loadCurrentUrl(){
let url = NSURL(string: textField.text)
let request = NSURLRequest(URL: url)
webView.loadRequest(request)
}
func webView(webView: WKWebView!, decidePolicyForNavigationAction navigationAction: WKNavigationAction!, decisionHandler: ((WKNavigationActionPolicy) -> Void)!) {
if navigationAction.navigationType == .LinkActivated{
UIApplication.sharedApplication().openURL(navigationAction.request.URL)
decisionHandler(.Cancel)
}else{
decisionHandler(.Allow)
}
}
}
First of all, you should set the delegate for the UIWebView.
Then, implement this method:
webView:shouldStartLoadWithRequest:navigationType
See the description of this method (Objective-C)
So, maybe you forgot to set the delegate. Check this ;)

Resources