如何从 Swift 中的 Appdelegate 调用视图控制器中的方法?

how to call a method in a view controller from Appdelegate in Swift?

此主菜单VC将在应用程序首次启动时或用户返回应用程序后打开(应用程序进入后台状态后激活)。

每次打开此主菜单 VC 时,理想情况下我需要更新日期时间数据来自服务器的时间。在这个主菜单中 vc class 我调用 getDateTimeFromServer() 然后我 updateUI().

但要在应用程序进入后台并返回前台后更新数据,getDateTimeFromServer()updateUI() 应使用函数从 Appdelegate 激活。

func applicationWillEnterForeground(application: UIApplication) {

    }

那么如何从 AppDelegate

激活主菜单 VC 中存在的方法

您不需要在应用委托中调用视图控制器方法。在你的控制器中观察前台事件并从那里调用你的方法。

在您的 viewController viewDidLoad:

中观察 UIApplicationWillEnterForeground 通知
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.yourMethod), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)

执行此操作以在用户进入前台时接收回调

@objc func yourMethod() {
     // Call getDateTimeFromServer()
}

你可以做类似的事情,使用一种叫做Key-Value观察:

的技术
class CommonObservableData: NSObject {
    // Use @objc and dynamic to ensure enabling Key-Value Observation
    @objc dynamic var dateTime: Date?

    static let shared = CommonObservableData()

    func updateFromWeb() {
        // callWebThen is a function you will define that calls your Web API, then
        // calls a completion handler you define, passing new value to your handler
        callWeb(then: { self.dateTime = [=10=] })
    }
}

然后你使用 Swift 4 的新 NSKeyValueObservation.

观察它
class SomeViewController: UIViewController {
    var kvo: NSKeyValueObservation?
    func viewDidLoad() {
        ...
        kvo = CommonObservableData.shared.observe(
            \CommonObservableData.dateTime, { model, change in

            self.label.text = "\(model.dateTime)"

        })
    }
}

Key-Value观察本来是Objective-C的一种技术Swift4,这种技术可以让你观察属性(在 Objective-C) 中调用任何对象的 Key

因此,在前面的代码片段中,我们创建了一个 class,并将其设为单例,这个单例有一个名为 dateTime 的可观察对象 属性,我们可以在其中观察更改此 属性,并在此 属性 中进行任何更改会自动调用我们可以更新 UI.

的方法

在此处阅读有关 KVO 的信息:

Key-Value Observation Apple Programming Guide

Key-Value Observation using Swift 4

此外,如果您喜欢 Rx 和 RFP(反应式函数式编程),您可以使用 RxSwift 并使用它以更简洁的方式进行观察。

这些类型的消息传递在大多数情况下是通过 static 上下文完成的。正如已经提到的,您可以选择使用视图控制器内的通知中心来通知您的应用程序进入前台。不过,我不鼓励您为此创建自定义通知(但这也是一种可能的解决方案)。

无论如何,对于你的具体情况,我建议你有一个包含你的数据的模型。然后创建它的共享实例。

class MyDataModel {

   static var shared: MyDataModel = {
        let model = MyDataModel()
        model.reloadData()
        return model
   }()

   var myObjects: [MyObject]?

   func reloadData() {
       // load data asynchronously
   }
}

现在,当您的视图控制器需要重新加载时,它只需使用 MyDataModel.shared.myObjects 作为数据源。

在应用程序委托中,您所做的就是在应用程序返回前台时使用 MyDataModel.shared.reloadData() 重新加载它。

所以现在还缺少代表所以我们添加

protocol MyDataModelDelegate: class {
    func myDataModel(_ sender: MyDataModel, updatedObjects objects: [MyObject]?)
}
class MyDataModel {

    weak var delegate: MyDataModelDelegate?

   static var shared: MyDataModel = {

现在,当您的视图控制器出现时,它需要将自己指定为委托 MyDataModel.shared.delegate = self。并实施必须重新加载视图的协议。

可以简单地在模型中完成对委托的标注 setter:

}()

var myObjects: [MyObject]? {
   didSet {
       delegate.myDataModel(self, updatedObjects: myObjects)
   }
}

func reloadData() {

在 swift 4 和 5 中,通知名称更改为适用于两者的以下代码。

    notifyCenter.addObserver(self, selector: #selector(new), name:UIApplication.willEnterForegroundNotification, object: nil)

 @objc func  new(){}