在我的应用程序中从我的 Today Extension(小部件)打开 Safari

Posted

技术标签:

【中文标题】在我的应用程序中从我的 Today Extension(小部件)打开 Safari【英文标题】:Open Safari from my Today Extension (widget) within my app 【发布时间】:2018-01-23 12:27:56 【问题描述】:

我有一个带有文本字段的 Today Extension。我想使用文本字段的内容作为 URL 在我的应用程序中打开浏览器。

这是我的小部件的 TodayViewController.swift

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")
        
    )

【问题讨论】:

您必须使用深层链接。 我是 Swift 新手。你能举个例子吗? 【参考方案1】:

您可以使用 @Giuseppe_Lanza 解决方案并解析您从 Today Extension Widget 收到的 url。但是,我将展示一个示例,其中您的 url 有一个静态组件,并根据用户在 textField 中的输入来查找诸如 https:/www.apple.com/homepodhttps:/www.apple.com/iphone 之类的路径:

1- URL 方案:myAppName

2- 添加此项以使用小部件打开您的应用

@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

定义一个变量并将接收到的url传递给webViewController,将在那里解析url。

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)

确保在属性下为这个segue添加一个标识符 检查员为toDeepLink

4- WebView & 解析 url 现在你可以像这样得到receivedUrl

    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)

否则,您需要像字典一样以适当的方式对其进行解析,以便将动态值分配给字典中的各个键,从而分配给您的 url,或者在您尝试附加 url.query 之前将 "?" 附加到您的 urlToLoad就像我在 webView 控制器中所做的那样。

【讨论】:

【参考方案2】:

您可以通过使用深层链接来做到这一点。

第一个define a custom URL scheme

一旦您的应用响应自定义方案my-app://,您就可以从 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")
        
    )

在您的应用中,就像在上一个链接中描述的那样,您必须在您的应用委托中实现

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

在这种方法中,网址将是您在应用扩展中创建的网址。这意味着它将是my-app://openurl/the url with percent escaping 您将必须解析此 url,初始化包含 webView 的视图控制器并传递要打开的 url。

【讨论】:

我添加了一个自定义 URL 以从我的小部件打开应用程序。检查我代码中的最后一个方法 请阅读我的其余答案。 let myAppUrl = URL(string: "main-screen:")! 这不是有效的网址。正如我所说,请阅读我的其余答案 我想在我的应用程序中使用 SafariServices 打开带有 safari 的 url,我尝试了你的代码,但我不知道如何在 safari 中打开它。我知道 safari 代码看起来像这样 @ 987654327@ 但我把它放在哪里? @cs4alhaider 正如我所说,如果您阅读我的回答,您会找到解决方案。当您按下按钮时,我为函数goButton 编写的代码将导致您的应用程序被打开(当然,将应用程序架构从my-app:// 更改为您决定使用的任何sceme。当您的应用程序打开应用程序委托方法时func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool 将被调用。这里你必须解析参数中的url,提取你想在safari中显示的url并启动safari view controller来显示url。

以上是关于在我的应用程序中从我的 Today Extension(小部件)打开 Safari的主要内容,如果未能解决你的问题,请参考以下文章

在 python 中从我的模块中的另一个文件夹导入模块函数

Today 扩展的安装

我如何在自己的网络中从我的公共IP访问我的网页?

在 listview 适配器中从我的应用程序打开电子邮件应用程序 [重复]

我如何在swiftui中从我的应用程序中的任何视图访问这个:@Environment(\.managedObjectContext) var context? [关闭]

如何在 IOS 中从我的 React-Native 应用程序打开外部应用程序?