[英]how to call a method in a view controller from Appdelegate in Swift?
這個Main Menu VC會在應用第一次啟動時或用戶返回應用后(應用進入后台狀態后激活)打開。
每次打開這個主菜單 VC 時,理想情況下我需要更新日期時間數據來自服務器的時間。 在這個主菜單 vc 類中,我在updateUI()
getDateTimeFromServer()
) 。
但要在應用程序進入后台並返回前台后更新數據,應使用函數從 Appdelegate 激活getDateTimeFromServer()
和updateUI()
。
func applicationWillEnterForeground(application: UIApplication) {
}
那么如何從 AppDelegate 激活 Main Menu 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 Observation的技術來做類似的事情:
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 = $0 })
}
}
然后您使用 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 Observation 最初是一種 Objective-C 技術,在 Swift 4 中“有所復興”,這種技術允許您觀察任何對象的屬性(在 Objective-C 中稱為Key )的變化。
因此,在前面的代碼片段中,我們創建了一個類,並將其設為單例,這個單例有一個名為dateTime
的可觀察屬性,我們可以在其中觀察該屬性的變化,並使該屬性的任何變化自動調用一個方法,其中我們可以更新用戶界面。
在此處閱讀有關 KVO 的信息:
此外,如果您喜歡 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
。 並實施必須重新加載視圖的協議。
對委托的標注可以簡單地在模型設置器中完成:
}()
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(){}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.