在 ViewController viewDidLoad 之前执行 NSApplicationDelegate 代码

Posted

技术标签:

【中文标题】在 ViewController viewDidLoad 之前执行 NSApplicationDelegate 代码【英文标题】:Executing NSApplicationDelegate Code Before ViewController viewDidLoad 【发布时间】:2017-01-19 01:47:59 【问题描述】:

我的 Swift 3,Xcode 8.2 MacOS 应用程序通过 Web 服务调用加载多个表。由于这些表被我的七个视图控制器中的一个或多个使用,我将它们放在 AppDelegate 中。

问题在于 AppDelegate 方法 applicationWillFinishLaunchingapplicationDidFinishLaunching 在 ViewController viewDidLoad 方法之后运行

因此,表格视图不显示任何数据。通过调用从 ViewController viewDidLoad 方法之一加载数据的 appDelegate 方法,我能够使其正常工作。由于任何 ViewController 都可以在应用程序启动时被调用,因此我必须添加对所有 ViewController 的调用以及某种标记方法以防止冗余负载。

我的问题是:在哪里可以放置在 ViewControllers 加载之前执行的代码?该代码将数据加载到多个字典数组中。这些数组在 AppDelegate 中。

我阅读了 @NSApplicationMain 并将其替换为 main.swift。我假设此时没有任何应用程序对象被实例化,因此我无法调用它们的方法,也不认为我的代码在类之外是有效的。

我的 appDelegate 的相关部分:

class AppDelegate: NSObject, NSApplicationDelegate 

var artists: [[String:Any]]? = nil

var dispatchGroup = DispatchGroup() // Create a dispatch group

func getDataFromCatBox(rest: String, loadFunction: @escaping ([[String: Any]]?) -> Void) 
    let domain = "http://catbox.loc/"
    let url = domain + rest
    var request = URLRequest(url: URL(string: url)!)
    request.httpMethod = "Get"
    let session = URLSession.shared
    var json: [[String:Any]]? = nil
    dispatchGroup.enter()
    session.dataTask(with: request)  data, response, err in
        if err != nil 
            print(err!.localizedDescription)
            return
        
        do 
            json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [[String: Any]]
        
        catch 
            print(error)
        
        loadFunction(json)
        self.dispatchGroup.leave()
    .resume()


    func loadArtistTable(array: [[String: Any]]?) 
    artists = array
    

ViewController 代码:

override func viewDidLoad() 
    super.viewDidLoad()

    appDelegate = NSApplication.shared().delegate as! AppDelegate
    appDelegate.getDataFromCatBox(rest: "artists.json", loadFunction: appDelegate.loadArtistTable)
    appDelegate.dispatchGroup.wait()
    artistTable.reloadData()

代码的工作原理是在窗口出现时填充 TableView。虽然代码不多,但我必须在所有视图控制器中进行复制。

这是一个原型。生产版本将有 14 个表和调用。

【问题讨论】:

为什么不让包含表格视图的窗口在启动时不可见?然后在didFinishLaunching中,加载表格数据,然后显示窗口。 【参考方案1】:

我想我的评论应该是一个答案。所以。为什么不让包含表格视图的窗口在启动时不可见?然后在didFinishLaunching中,加载表格数据,然后显示窗口。

【讨论】:

我在问题中添加了 ViewController 代码。你所看到的有效。我正在寻找更清洁的东西。我认为隐藏和显示窗口同样需要额外的代码。【参考方案2】:

我认为没有任何方法可以按照问题中的结构方式做我想做的事情。 ViewController 代码可以简化为

appDelegate = NSApplication.shared().delegate as! AppDelegate
appDelegate.getDataFromCatBox(rest: "artists.json", loadFunction: appDelegate.loadArtistTable

通过在 AppDelegate 中创建一个包含等待的包装函数。它还可以包含一个标志,指示给定的表已经加载,以免进行冗余调用。

我最终采用了不同的方法:我为每个表创建了一个带有单例子类的超类。现在我的 viewDidLoad 方法如下所示:

artists.loadTable()  // The sublass
artistTable.reloadData()

如果有人对原始问题提出更简洁的解决方案,我会接受他们的答案来代替我的答案。

【讨论】:

谢谢@curt。像这样设置appDelegate 救了我!

以上是关于在 ViewController viewDidLoad 之前执行 NSApplicationDelegate 代码的主要内容,如果未能解决你的问题,请参考以下文章

swift5.x 扩展(extension)

9_Permanent Storage

TableView 由于核心数据错误而崩溃/冻结

数组不存储值

XIB 拖控件

SVProgressHUD 无法显示状态