问题
This question must be simple, but I am a newbie. I have a splitView that I am trying to manage as a Master-Detail relationship. The user clicks on an OutlineView item in the Master and that triggers a need to update the content of a PopUp button on the Detail side. I have tried several tests of the arrangement in the larger code from which the code below is extracted (See TEST 1, TEST 2, TEST 3, TEST 4 marked in the code below. The one that fails is TEST 3 and it fails because displayListPopUP is nil in the protocol function when it is called by the delegate although it is not nil when the class DetailViewController initially loads the PopUp with the same instructions. How do I repair 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:
This seems to solve the problem:
var detailViewController = DetailViewController()
weak var delegate: detailViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
...
detailViewController =
self.storyboard?.instantiateController(withIdentifier: "detailVC") as! NSViewController as! DetailViewController
// This is a trick to force the detailViewController to load its hierarchy view, icluding displayListPopUP
_ = detailViewController.view
... }
xcode does, indeed, show an active outlet to my PopUp. The initial display of DetailViewController is apparently managed by macOS with its own instantiation of the view. Thus Test 4 does work.
Creating the master-detail relationship apparently requires a new instantiation of my DetailViewController. Since I am using Storyboard, nibs and xibs, if they exist, are out-of-sight and out-of-mind. Thus, @OOper's instantiation had to be replaced with the one shown. But, he is correct, the instantiation does not load the view hierarchy. At that point Test 3 would fail because displayPopUP would still be nil. The view hierarchy is loaded after the first reference to the view and the dummy call that is shown forces the hierarchy to load, with the displayPopUP now active. Test 3 is now successful.
来源:https://stackoverflow.com/questions/49787805/macos-swift-master-detail-delegate-protocol-not-working