如何从 App Delegate 访问视图控制器 (XCode 9)

How to I access View Controllers from App Delegate (XCode 9)

我有一个带有拆分视图的故事板。当应用程序启动时,我想为视图设置模型。

我有一个简单的class天:

import Foundation

class Day: NSObject{
    var date: Date
    var sleep: Double
    init(date: Date, sleep: Double){
        self.date = date
        self.sleep = sleep
        super.init()
    }
    override convenience init(){
        self.init(date: Date(), sleep: 8.0)
    }
}

我有一个拆分窗格的视图控制器:

import Cocoa

class DayViewController: NSViewController {

    private var day: Day = Day()

    @IBOutlet weak var sleep: NSTextField!

    func set(day: Day){
        self.day = day
        //update()
    }

//    func update(){
        //sleep.doubleValue = day.sleep
  //  }   
}

我想在应用程序委托中设置日,以便显示它。

如何在 AppDelegate 中获取 DayViewController 的实例以便我可以设置该值?

你试过这个吗?

    if  window?.rootViewController is DayViewController {
        guard let dayVC =  window?.rootViewController as? DayViewController else {
            //there was an error
            return
        dayVC.set(day: new Day())
    }

我不确定它是否有效。也许最好按照@Siyavash 所说的方式进行...放入 viewDidLoad 本身。

这就是我最终所做的。认为它可能很有趣。仍然不确定这是否是黑客攻击。

在 DayViewController 中,我在 AppDelegate 中设置了对它的引用:

override func viewDidLoad() {
    super.viewDidLoad()
    let app: AppDelegate = NSApplication.shared.delegate as! AppDelegate
    app.dayViewController = self
}

然后我可以在 AppDelegate 中设置视图的日期:

var dayViewController: DayViewController?

func applicationDidFinishLaunching(_ aNotification: Notification) {
    let day: Day = Day.init(date: Date(), sleep: 9.5)
    dayViewController!.set(day: day)
}

根据评论中的要求,这是我现在所做的,我对 swift 有了更多的经验。

该示例使用了一个简单的“Day”class 作为我的模型,但在我的实现中该模型被称为“TrainingDiary”。现在,我的 AppDelegate 中几乎没有任何内容。相反,我做了以下事情:

  1. 我有所有提供模型视图的视图控制器实现的协议

    protocol TrainingDiaryViewController{
        func set(trainingDiary td: TrainingDiary)
    }
    
  2. 我有主 window 的视图控制器,它现在有一个 TabViewController(而不是我的拆分视图,但这种方法适用于此)。

  3. 在那个视图控制器中我重写了 prepare(for:sender:):

    override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
        super.prepare(for: segue, sender: sender)
    
        guard let tabViewController = segue.destinationController as? NSTabViewController else {return}
    
        for controller in tabViewController.childViewControllers{
            if let c = controller as? TrainingDiaryViewController{
                trainingDiaryVCs.append(c)
            }
        }
    }
    

    这意味着我现在可以引用作为 TrainingDiary 视图的所有视图控制器

  4. 在主视图中有一个 TableView,我用它来管理培训日记(即添加、删除、select)。主视图控制器设置为 TableViews 委托,TableView 在 IB 中设置为具有单个 selection 并避免没有 selection。然后我实施了:

    func tableViewSelectionDidChange(_ notification: Notification) {
        if let trainingDiary = trainingDiarysArrayController.selectedObjects[0] as? TrainingDiary{
    
            for c in trainingDiaryVCs{
                c.set(trainingDiary: trainingDiary)
            }
        }
    }
    

一切都很好。