12

I have an app that is currently using a webview and when certain links are clicked in the webview, it opens those links in Safari. I now want to implement the Safari View Controller(SVC) instead of booting it to the Safari app. I have done research and looked at examples on the SVC; however, all I see are ones that open the SVC from the click of a button. Does anyone have any suggestions for me to look at or to try?

Here is some of my code:

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
    if navigationType == UIWebViewNavigationType.LinkClicked {
        let host = request.URL!.host!;
        if (host != "www.example.com"){
            return true
        } else {
            UIApplication.sharedApplication().openURL(request.URL!)
            return false
        }
    return true

}

func showLinksClicked() {

    let safariVC = SFSafariViewController(URL: NSURL(string: "www.example.com")!)
    self.presentViewController(safariVC, animated: true, completion: nil)
    safariVC.delegate = self    }

func safariViewControllerDidFinish(controller: SFSafariViewController) {
    controller.dismissViewControllerAnimated(true, completion: nil)
}
Mike
  • 4,550
  • 4
  • 33
  • 47
beginnercoder
  • 133
  • 1
  • 1
  • 6

7 Answers7

18

If I am understanding correctly you are loading a page on webview which has certain links now when user clicks on link you want to open those page in SVC. You can detect link click in webview using following delegate method and then open SVC from there.

EDIT

Based on edited question I can see that you are not calling showLinksClicked func , you can call this function as I have updated in following code and it should work.

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
    if navigationType == UIWebViewNavigationType.LinkClicked {
       self.showLinksClicked()
       return false

    }
    return true;
}


func showLinksClicked() {

    let safariVC = SFSafariViewController(url: URL(string: "www.google.com")!)
    present(safariVC, animated: true, completion: nil)
    safariVC.delegate = self
}

func safariViewControllerDidFinish(controller: SFSafariViewController) {
    controller.dismissViewControllerAnimated(true, completion: nil)
}
Sharad Chauhan
  • 4,821
  • 2
  • 25
  • 50
Bhumit Mehta
  • 16,278
  • 11
  • 50
  • 64
13

For Swift 3:

First, import SafariServices and integrate the delegate into your class:

import SafariServices

class YourViewController: SFSafariViewControllerDelegate {

Then, to open Safari with the specified url:

let url = URL(string: "http://www,google.com")!
let controller = SFSafariViewController(url: url)
self.present(controller, animated: true, completion: nil)
controller.delegate = self

And now you can implement the delegate callback to dismiss safari when the user is finished:

func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
    controller.dismiss(animated: true, completion: nil)
}
vikzilla
  • 3,998
  • 6
  • 36
  • 57
10

This piece of code will allow you to do this.

let safariVC = SFSafariViewController(URL: NSURL(string: "https://www.google.co.uk")!)
self.presentViewController(safariVC, animated: true, completion: nil)
safariVC.delegate = self

You may need to add this to the top of the class as well:

import SafariServices
onemillion
  • 682
  • 5
  • 19
  • should this just be added onto my current code? Or do I put it in there instead of some of my code? If I just add it in there nothing different happens – beginnercoder Jul 05 '16 at 13:06
  • You will have to put it either in your viewDidLoad or viewWillAppear function. In my application this is attached to a button so when you click it the page appears in safari. – onemillion Jul 05 '16 at 14:04
  • Ok, see I don't have a button that it is linked to. I am wanting it to opein the SVC when some links in the app are clicked. (ex: Contact Us, About Us, etc) My webview calls a website with these links so I have no control of the initial code of the website – beginnercoder Jul 05 '16 at 14:16
3

Solution For Swift 4

Step 1:

import Safari Service In you Class

import SafariServices

Step 2:

Import SFSafariViewControllerDelegate in With your View Controller

class ViewController: UIViewController,SFSafariViewControllerDelegate {...}

Step 3:

Create A function to Open Safari View Controller.

 func openSafariVC() {

            let safariVC = SFSafariViewController(url: NSURL(string: "https://www.google.com")! as URL)
            self.present(safariVC, animated: true, completion: nil)
            safariVC.delegate = self
        }

        func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
            controller.dismiss(animated: true, completion: nil)
        }

Step 4:

call the function openSafariVC

openSafariVC()

Note: Don't forget To Add Navigation Controller with your View Controller.

Now your SafariVC is ready to open your Link within an app without Using UIWebView Oe WKWebView

Anup Gupta
  • 1,993
  • 2
  • 25
  • 40
  • is there any way where I can directly open SFSafariViewController so I do not have to call openSafariVC()? for now I am using doing this > https://paste.ubuntu.com/p/RGmFqR76Dv/ but I only want to use SFSafariViewController. – Shahid Ghafoor Sep 24 '20 at 13:41
  • @ShahidGhafoor SFSafariViewController is for to open on any click event else you can open a web page inside ViewController with WKWebView so no need to redirect from VC to SFVC. – Anup Gupta Sep 24 '20 at 18:55
2

Follow the steps :

On your controller file(e.g. ViewController.swift) import SafarriServices.

import SafariServices

Then where you want to open link write

let controller = SFSafariViewController(URL: NSURL(string: "https://www.google.co.uk")!)
self.presentViewController(controller, animated: true, completion: nil)
controller = self
Dipen Patel
  • 911
  • 2
  • 9
  • 22
1

Swift 4.2

This is how you can open-up Safari browser within your application.

import SafariServices

whenever you want to open, like wise on

@IBAction func btnOpenWebTapped(_ sender: UIButton) {
    self.openWeb(contentLink: "https://www.google.com")
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    self.openWeb(contentLink: "https://www.google.com")
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
     self.openWeb(contentLink: "https://www.google.com")
}

by write the custom function be like and you can customise the properties of the SFSafariViewController, preferredBarTintColor, preferredControlTintColor, dismissButtonStyle, barCollapsingEnabled

func openWeb(contentLink : String){
     let url = URL(string: contentLink)!
     let controller = SFSafariViewController(url: url)
     controller.preferredBarTintColor = UIColor.darkGray
     controller.preferredControlTintColor = UIColor.groupTableViewBackground
     controller.dismissButtonStyle = .close
     controller.configuration.barCollapsingEnabled = true
     self.present(controller, animated: true, completion: nil)
     controller.delegate = self
}

last and the most important thing is don't forget to bind the delegate of the SFSafariViewController with your view controller. you can do this by below mentioned extension code.

extension YourViewController: SFSafariViewControllerDelegate
{
    func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
        controller.dismiss(animated: true, completion: nil)
    }
}

Happy coding Thank you :)

Azharhussain Shaikh
  • 1,654
  • 14
  • 17
1
import SafariServices

class ViewController: UIViewController, SFSafariViewControllerDelegate {

 override func viewDidLoad() {
     super.viewDidLoad()
     DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
         let url = URL(string: "http://www.google.com")!
         let controller = SFSafariViewController(url: url)
         self.present(controller, animated: true, completion: nil)
         controller.delegate = self
     }
 }

 func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
     dismiss(animated: true)
 }
}
Vinoth Anandan
  • 1,157
  • 17
  • 15