【问题标题】:Calling custom delegate from AppDelegate in Swift在 Swift 中从 AppDelegate 调用自定义委托
【发布时间】:2015-07-02 08:47:48
【问题描述】:

我在 AppDelegate.swift 中有这个委托,一旦另一个应用使用 url 方案打开我的应用,它就会触发。

AppDelegate.swift

 func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
        return true
 }

当另一个应用程序使用 url 方案打开我的应用程序时它会触发,但是当这个函数触发时,我想通知某个 ViewController。我想我可以使用自定义委托来做到这一点,并让 AppDelegate 通知曾经实现我的委托的人有人打开了应用程序。

MyDelegate.swift

protocol MyDelegate {
    func opened(hasBeenOpened: Bool!)
}

然后我的 ViewController 实现了这个 Delegate

LoginViewController.swift

import UIKit

/* Obviously this class has more code and other functions, 
but for the illustration of the problem, I removed all the other unrelated things.*/

class LoginViewController: UIViewController, MyDelegate {
    func opened(hasBeenOpened: Bool!) {
        print(hasBeenOpened)
    }
}

到目前为止一切顺利,但让我们回到 AppDelegate.swift 中的 openURL() 函数并尝试调用 MyDelegate.opened()。这是我完全迷失的地方。

AppDelegate.swift

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {

        print("openURL delegate running")

        if var delegate = MyDelegate?() {
            delegate.opened(true)
        }

        return true
    }

控制台打印“openUrl delegate running”,所以它正在运行,但我的委托变量变为nil。我缺少一些初始化吗?

我似乎无法弄清楚如何从 AppDelegate 调用我自己的自定义委托。有没有另一种方法来通知 ViewControllers 这已经发生了?或者这总体上是一个坏主意,还有另一种被认为更好的方法吗?

提前谢谢大家,非常感谢您的帮助。

【问题讨论】:

  • 我不确定代表是实现这一目标的适当方式。问题是您需要在 AppDelegate 中有一个委托变量,然后在 LoginViewController 中设置它。但是在您的 openURL 方法中,您可能还没有实例化的 LoginViewController。你只想显示 LoginViewController 吗?
  • 我基本上想在 LoginViewController 上调用 openURL 方法的函数。但是从 AppDelegate 调用 ViewController 上的函数似乎很奇怪。我想我宁愿注册一个委托,这样曾经实现过委托的人就可以监听事件。
  • 不只是delegate,你的VC对象也会是nil,请问你想做什么,我是说通知VC做什么?
  • @VinayJain 我正在使用第三方银行应用程序对我的用户进行身份验证,当身份验证完成后,银行应用程序再次使用 url 方案打开我的应用程序。发生这种情况时,AppDelegate 中的 openURL 正在运行。我只是想通知我的 LoginViewController 用户已尝试使用银行应用程序进行身份验证,因此我可以从银行 Web 服务收集登录信息并查看它是否成功。

标签: ios swift swift2


【解决方案1】:

不详细说明这是个好主意还是坏主意,问题是AppDelegate 中的delegate 属性永远不会初始化。在 UIViewController 的初始化方法中,您需要访问 AppDelegate 并将委托属性设置为 self

【讨论】:

    【解决方案2】:

    您正在尝试初始化一个不可能的协议 (var delegate = MyDelegate?())。

    您使用委托的方式是在一个类上注册一致性,您在 LoginViewController 中执行此操作,并直接在该类的实例上调用协议中定义的方法。

    例如:

    var loginViewController = // get an instance of LoginViewController
    loginViewController.opened(true)
    

    在这种情况下,您无权访问实例,在 App Delegate 中保留对视图控制器的引用也不被认为是好的做法。所以我认为你正在寻找的范式是通知。查看NSNotificationCenterNSHipster article on notifications 的文档。

    【讨论】:

    • 由于类的封装,从 AppDelegate 调用 LoginViewController 上的函数是否被认为是一种不好的做法。我不一定希望我的 AppDelegate 知道我的 LoginViewController。也许通知是一个很好的解决方案。
    • @StefanKonno 我同意,nsnotification 可能是一个很好的解决方案,但这取决于你到底想做什么。如果没有实例化LoginViewController,你的方法就不会被调用,是不是有问题?
    • LoginViewController 是我的应用程序的入口点,所以当我在 AppDelegate 中的 openURL 运行时,它应该总是被实例化。否则我会确保的。
    • @StefanKonno 是的,除了应用程序的根视图控制器可能例外,我永远不会引用来自应用程序委托的 UI 元素,因为它旨在与系统交互。
    • 是的,这正是我的想法。这就是为什么我认为我会注册一个 ViewController 可以监听的事件。那我会看看通知而不是代表。谢谢。
    【解决方案3】:

    试试 NSNotification,我认为在 AppDelegate 中持有特定的视图控制器不是一个好主意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-27
      • 1970-01-01
      相关资源
      最近更新 更多