【问题标题】:Custom URL Scheme with App running in background应用在后台运行的自定义 URL 方案
【发布时间】:2019-05-19 15:45:35
【问题描述】:

我创建了一个自定义 URL 方案以从其他应用程序启动我的应用程序。如果应用程序未打开,这适用于 Safari。它用函数加载 AppDelegate:

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

问题是当我打开应用程序并通过点击主页按钮将其置于后台时。我设置为在 AppDelegate 中接收文本的变量不会再次被击中。我在我的主 VC 中设置了一个通知程序,当我将应用程序带回前台时它可以工作,但是我在 viewDidLoad 上引用的变量是空的,因为它是从 AppDelegate 读取的。根据 Apple 的文档,当创建自定义 url 方案时,它会点击上面的函数。

系统通过调用您的应用代理的 application(_:open:options:) 方法将 URL 传递给您的应用。

有一个用于 applicationWillEnterForeground 的函数,但如果不调用该方法,我不确定如何将自定义 URL 接收到该函数中。

这是我目前所拥有的:

AppDelegate:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var receivedURL: URL?

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

        receivedURL = url
        return true
    }

在 MainViewController 中:

    let appDelegate = UIApplication.shared.delegate as? AppDelegate

    override fun viewDidLoad() {
       if appDelegate?.receivedURL != nil {
           urlToDecodeTextView.text = appDelegate?.receivedURL?.absoluteString
        }

NotificationCenter.default.addObserver(self, selector: #selector(handleLinks), name: UIApplication.willEnterForegroundNotification, object: nil)


    }

   @objc func handleLinks(notification: Notification) {
        print("made it back")  <-- This prints
        let test = appDelegate?.receivedURL <-- this is always nil
        urlToDecodeTextView.text = test?.absoluteString
    }

这是我拥有的原始代码。如果应用程序未打开,则此代码效果很好,但如果应用程序在后台运行,则不会。我确实注意到 appdelegate 函数每次都会运行,但是当通知程序发生时,该值是 nil - 即使它是在 appdelegate 中设置的。

我最终想要做的是能够从电子邮件(文本或 URL)中复制 URL,并与我的应用程序共享。当它被共享时,我的应用程序应该在适当的文本视图中打开 url。我认为使用自定义 URL 方案并处理重写链接可能更容易,但这已被证明是一个挑战。

【问题讨论】:

  • application(_:open:options:) 在通过自定义 URL 方案打开时被调用,即使是从后台调用。
  • viewDidLoad 方法已经被调用,不会再被调用。您应该在AppDelegate 中设置一个全局变量,并将其设置在application(_:open:options:) 方法中(从其他应用程序打开时将调用该方法)。然后从viewWillAppear 方法中读取变量。如果您打开了不同的viewController,那么您仍然不会得到它。当通过 URL 方案打开应用程序时,您应该导航到正确的 viewController(例如弹回 rootViewController 等)。
  • @RJE 我在 appdelegate 中设置了全局变量,但它似乎没有命中主 VC 中的 viewWillAppear 方法。它确实再次命中了 appdelegate 中的函数,但如果应用程序正在运行,则不会命中 viewWillAppear 方法。这需要发送到的屏幕是主 VC,它是打开的那个。
  • 应用返回前台时,不会调用任何视图控制器生命周期方法。
  • 查看stackoverflow.com/questions/49961541/… 以获得实用的解决方案。

标签: swift appdelegate url-scheme


【解决方案1】:

而不是这个通知

NotificationCenter.default.addObserver(self, selector: #selector(handleLinks), name: UIApplication.willEnterForegroundNotification, object: nil)

你可以这样做

一些可公开访问的通知 NSNotification.Name

let customNotifKey = NSNotification.Name("InterAppURLReceived")

然后改变监听器

var receivedURL: URL? {
    didSet {
        if receivedURL != nil {
            NotificationCenter.default.post(name: customNotifKey, object: nil)
        }
    }
}

终于在VC中捕捉到通知

        NotificationCenter.default.addObserver(self, selector: #selector(handleMethod(_:)), name: customNotifKey, object: nil)

现在你的 VC 会知道什么时候设置了变量。

首先,检查viewWillAppear方法中的变量。如果未收到,请在收到时通知您

【讨论】:

  • 谢谢!这似乎已经解决了“前台”问题,但如果另一个应用程序使用自定义 URL 启动我的应用程序,它似乎不起作用。这可能是一个 xcode 问题,但在调试时,我看到它设置了 receiveURL 变量,但它从未在主 VC 中点击 viewDidLoad。如果应用程序已经在运行并且我发送了一个自定义 URL,那么一切都会按预期运行。
  • 你的意思是它没有点击viewDidLoad。通知可用于后台和前台场景。对于新启动,您只需检查 viewWillAppear 方法中的变量。您只是对系统在两种情况下调用每个方法的顺序感到困惑。您可以放置​​一些断点并检查在您的 2 个场景中哪个方法首先命中并采取相应措施
  • 这是因为我更改了调试器附加到正在运行的应用程序的方式。我改回来了,没问题。这并不完全按照我想要的方式工作,但我认为我还有另一个问题。感谢您的所有帮助!
猜你喜欢
  • 2014-06-16
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
  • 1970-01-01
  • 2014-04-02
  • 2012-06-15
  • 2011-04-30
  • 2014-10-22
相关资源
最近更新 更多