1

I have a Today Extension with a text field. I want to use the contents of the text field as a URL to open a browser within my app.

This is my TodayViewController.swift for my widget

import UIKit
import SafariServices
import NotificationCenter

// This extension to remove the white spaces from what pasteed   
extension String {
func replace(string:String, replacement:String) -> String {
    return self.replacingOccurrences(of: string, with: replacement,             
options: NSString.CompareOptions.literal, range: nil)
}

func removeWhitespace() -> String {
    return self.replace(string: " ", replacement: "")
}
}


class TodayViewController: UIViewController, NCWidgetProviding {

var clearNumber: String?

override func viewDidLoad() {
    super.viewDidLoad()

}


func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
    // Perform any setup necessary in order to update the view.

    // If an error is encountered, use NCUpdateResult.Failed
    // If there's no update required, use NCUpdateResult.NoData
    // If there's an update, use NCUpdateResult.NewData

    completionHandler(NCUpdateResult.newData)
}



@IBOutlet weak var textBox: UITextField!

@IBAction func clearNumber(_ sender: Any) {

    if textBox.hasText == true {
        textBox.text = ""
    }else{
        return
    }

}

@IBAction func pasteNumber(_ sender: Any) {

    if let myString = UIPasteboard.general.string {
        let pasteNumber = myString.removeWhitespace()
        textBox.insertText(pasteNumber)
    }else{
        return
    }
}

@IBAction func goButton(_ sender: Any) {

    let myAppUrl = URL(string: "main-screen:")!
    extensionContext?.open(myAppUrl, completionHandler: { (success) in
        if (!success) {
            print("error: failed to open app from Today Extension")
        }
    })
}
jscs
  • 63,694
  • 13
  • 151
  • 195
cs4alhaider
  • 1,318
  • 1
  • 17
  • 26

2 Answers2

4

You could use @Giuseppe_Lanza solution and parse url that you receive from Today Extension Widget. However, I would show an example where your url have a static components and looking for a path such as https:/www.apple.com/homepod or https:/www.apple.com/iphone based on user's input in the textField:

1- URL Scheme: myAppName

2- Add this to open your app with widget

@IBAction func goButton(_ sender: Any) {
    openApp(widgetText: "\(textBox.text!)")
}

func openApp(widgetText:String)    {

    let str = "myAppName://https://www.apple.com/\(widgetText)"
    let url = URL(string: str)!
    if textBox.hasText == true  {

        extensionContext?.open(url, completionHandler: { (success) in
            if (!success) {
                print("error:  ")
            }
        })
    }
}

3- AppDelegate

Define a variable and pass received url to webViewController, will parse url there.

open var receivedUrl:URL?

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool{

    receivedUrl = url
    //You need to alter this navigation to match your app requirement so that you get a reference to your previous view..
    window?.rootViewController?.performSegue(withIdentifier: "toDeepLink", sender: nil)
}

Make sure to make add an identifier for this segue under the attributes inspector as toDeepLink.

4- WebView & parsing url Now you can get the receivedUrl like this

    override func viewDidLoad() {
    super.viewDidLoad()

    let myAppDelegate = UIApplication.shared.delegate as! AppDelegate
    print("receivedUrl \(myAppDelegate.receivedUrl!)")
    //url Parsing & getting rid off urlScheme
    let urlToLoad = URL(string: "\(myAppDelegate.receivedUrl!.host! + ":" + myAppDelegate.receivedUrl!.path)")!
    print(urlToLoad)
    let urlRequest = URLRequest(url: urlToLoad)
    webView.load(urlRequest)
}

Else, you need to parse it in a proper way like dictionary to assign dynamic values to respective keys in your dictionary and hence to your url or append "?" to your urlToLoad just before you attempt to append url.query as I did in the webView controller.

Abdullah Jafar
  • 104
  • 1
  • 9
1

You can do this by using deep linking.

First define a custom URL scheme

Once your app responds to the custom scheme my-app:// you can open your app from your todayViewController.

@IBAction func goButton(_ sender: Any) {

    let myAppUrl = URL(string: "my-app://openurl/\(yourURL.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed))")!
    extensionContext?.open(myAppUrl, completionHandler: { (success) in
        if (!success) {
            print("error: failed to open app from Today Extension")
        }
    })
}

In your app, just like described in the previous link you will have to implement in your app delegate

func application(_ app: UIApplication, open url: URL, 
  options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool

in this method, the url will be the one you created in your app extension. Meaning it will be my-app://openurl/{the url with percent escaping} You will have to parse this url, initialise the view controller that contains the webView and pass the url to be opened.

Giuseppe Lanza
  • 3,519
  • 1
  • 18
  • 40
  • I had add a custom URL to open app from my widget.. check the last method in my code – cs4alhaider Jan 23 '18 at 15:53
  • Read the rest of my answer please. – Giuseppe Lanza Jan 23 '18 at 15:55
  • `let myAppUrl = URL(string: "main-screen:")!` this is not a valid url. As I said, read the rest of my answer – Giuseppe Lanza Jan 23 '18 at 15:56
  • I want to open the url with safari inside my app using SafariServices , i tried your code but i didn't know how to open it in safari .. i know the safari code is looks like this `let urlString = "https://google.com" print(urlString) if let url = URL(string: urlString) { let vc = SFSafariViewController(url: url) vc.delegate = self self.present(vc, animated: true) ` but where i put it ? – cs4alhaider Jan 23 '18 at 23:42
  • @cs4alhaider As I said, if you read my answer you will find the solution. When you press the button, the code I wrote for the function `goButton` will cause your app to be opened (of course change the app schema from `my-app://` to whichever sceme you decided to use. When your app opens the app delegate method `func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool` will be called. **Here** you must parse the url in parameter, extract the url you wanted to display in safari and start the safari view controller to show the url. – Giuseppe Lanza Jan 24 '18 at 10:29
  • I'm sorry, but I can't. I gave you all the info you need. You must just implement that method in your app delegate. – Giuseppe Lanza Jan 24 '18 at 13:08