macOS Swift master-detail委托/协议无法正常工作

时间:2018-04-12 04:01:46

标签: swift macos delegates protocols

这个问题必须简单,但我是新手。我有一个splitView,我试图将其作为Master-Detail关系进行管理。用户单击Master中的OutlineView项,这将触发更新Detail端的PopUp按钮内容的需要。我在较大的代码中尝试了几种排列测试,从中提取下面的代码(参见下面代码中标记的TEST 1,TEST 2,TEST 3,TEST 4。失败的是TEST 3,因为displayListPopUP失败了当委托人调用它时,协议函数中的nil是nil,尽管当DetailViewController类最初使用相同的指令加载PopUp时它不是nil。如何修复TEST 3?

import Cocoa

var displayList: [String] = []

class MasterViewController: NSViewController {

    weak var delegate: detailViewControllerDelegate?
    let detailViewController = DetailViewController()

    override func viewDidLoad() {
        super.viewDidLoad()
        displayList = ["Problem(s) in Selected Category","EM3", "EM4"]        
        self.delegate = detailViewController as          detailViewControllerDelegate

    // TEST 1---THIS WORKS (Bingo is printed)
        delegate?.testPrint(val: "Bingo")
}

}

extension MasterViewController: NSOutlineViewDelegate {

    func outlineViewSelectionDidChange(_ notification: Notification){

        displayList = ["Problem(s) in Selected Category","EM1", "EM2"]

    // TEST 2---THIS WORKS (Bingo 2 is printed)
        delegate?.testPrint(val: "Bingo 2")

    // TEST 3---THIS DOESN'T WORK (displayListPopUP is nil)
        delegate?.loadListPopUP(list: displayList)
    }
}

protocol detailViewControllerDelegate: class {
    func testPrint(val: String)
    func loadListPopUP(list: [String])
}


class DetailViewController: NSViewController, detailViewControllerDelegate     {

//I CHECK, XCODE SAYS THIS OUTLET IS ACTIVE
    @IBOutlet weak var displayListPopUP: NSPopUpButton!

    override func viewDidLoad() {
        super.viewDidLoad()

    //TEST 4---THIS WORKS (PopUp button is loaded correctly)
        displayListPopUP.removeAllItems()
        displayListPopUP.addItems(withTitles: displayList)
    }

    func testPrint(val: String){
        print(val)
    }

    func loadListPopUP(list: [String]){
    //THIS DOES NOT WORK.  displayListPopUP is nil when called from delegate
        displayListPopUP.removeAllItems()
        displayListPopUP.addItems(withTitles: list)
    }

}

1 个答案:

答案 0 :(得分:0)

这似乎解决了这个问题:

var detailViewController = DetailViewController()
weak var delegate: detailViewControllerDelegate?

override func viewDidLoad() {
    super.viewDidLoad()

...

detailViewController = 

self.storyboard?.instantiateController(withIdentifier:“detailVC”)as! NSViewController为! DetailViewController

 // This is a trick to force the detailViewController to load its hierarchy     view, icluding displayListPopUP

    _ = detailViewController.view

... }

实际上,xcode确实显示了我的PopUp的主动插座。 DetailViewController的初始显示显然由macOS管理,具有自己的视图实例。因此,测试4确实有效。

创建master-detail关系显然需要我的DetailViewController的新实例化。因为我使用的是Storyboard,nibs和xibs,如果它们存在的话,就会出现在视线之外并且不在乎。因此,@ OOper的实例化必须用显示的实例替换。但是,他是正确的,实例化不会加载视图层次结构。此时,测试3将失败,因为displayPopUP仍然是零。在第一次引用视图之后加载视图层次结构,并且显示的虚拟调用强制加载层次结构,displayPopUP现在处于活动状态。测试3现在成功了。