我正在使用Swift开发一个OSX应用程序,该应用程序使用一个NSSplitView,它包含两个视图控制器:“TableViewController”和“EntryViewController”。我正在使用委托,以便在从TableViewController到SplitViewController的点击时传输自定义NSObject(“Entry”),然后返回到EntryViewController。
我的问题是这个:当在EntryViewController中收到Entry对象时,任何将其属性分配给文本字段值的尝试都会导致意外找到nil 类型错误,不要介意IBOutlets正确链接,并且它可以打印Entry.property 和文本字符串值(假设它在不同的,无关的函数中)。
我已经尝试了很多安排来解决这个问题,这就是当前配置可能有点过于复杂的原因。直接从表VC到Entry VC的委托关系引起了同样的问题。
有没有某种方式IBOutlets没有连接,即使在调用委托之前加载了视图?我已经阅读了许多关于委托的许多文章 - 主要是针对iOS的 - 但似乎无法找到问题的根源。我是第一个承认我对Swift的掌握有点零碎的人,所以我很乐意接受这样的可能性,即我想要做的只是坏/ hacky编码,我应该尝试一些完全不同的东西。
感谢您的帮助!
TableViewController:
protocol SplitViewSelectionDelegate: class {
func sendSelection(_ entrySelection: NSObject)
}
class TableViewController: NSViewController {
@IBOutlet weak var searchField: NSSearchField!
@IBOutlet var tableArrayController: NSArrayController!
@IBOutlet weak var tableView: NSTableView!
var sendDelegate: SplitViewSelectionDelegate?
dynamic var dataArray = [Entry]()
// load array from .plist array of dictionaries
func getItems(){
let home = FileManager.default.homeDirectoryForCurrentUser
let path = "Documents/resources.plist"
let urlUse = home.appendingPathComponent(path)
let referenceArray = NSArray(contentsOf: urlUse)
dataArray = [Entry]()
for item in referenceArray! {
let headwordValue = (item as AnyObject).value(forKey: "headword") as! String
let defValue = (item as AnyObject).value(forKey: "definition") as! String
let notesValue = (item as AnyObject).value(forKey: "notes") as! String
dataArray.append(Entry(headword: headwordValue, definition: defValue, notes: notesValue))
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.sendDelegate = SplitViewController()
getItems()
print("TVC loaded")
// Do any additional setup after loading the view.
}
// send selection forward to entryviewcontroller
@IBAction func tableViewSelection(_ sender: Any) {
let index = tableArrayController.selectionIndex
let array = tableArrayController.arrangedObjects as! Array<Any>
let obj: Entry
let arraySize = array.count
if index <= arraySize {
obj = array[index] as! Entry
print(index)
print(obj)
sendDelegate?.sendSelection(obj)
}
else {
print("index unassigned")
}
}
}
SplitViewController:
protocol EntryViewSelectionDelegate: class {
func sendSecondSelection(_ entrySelection: NSObject)
}
class SplitViewController: NSSplitViewController, SplitViewSelectionDelegate {
var delegate: EntryViewSelectionDelegate?
@IBOutlet weak var mySplitView: NSSplitView!
var leftPane: NSViewController?
var contentView: NSViewController?
var entrySelectionObject: NSObject!
override func viewDidLoad() {
super.viewDidLoad()
// assign tableview and entryview as child view controllers
let story = self.storyboard
leftPane = story?.instantiateController(withIdentifier: "TableViewController") as! TableViewController?
contentView = story?.instantiateController(withIdentifier: "EntryViewController") as! EntryViewController?
self.addChildViewController(leftPane!)
self.addChildViewController(contentView!)
print("SVC loaded")
}
func sendSelection(_ entrySelection: NSObject) {
self.delegate = EntryViewController() //if this goes in viewDidLoad, then delegate is never called/assigned
entrySelectionObject = entrySelection
print("SVC:", entrySelectionObject!)
let obj = entrySelectionObject!
delegate?.sendSecondSelection(obj)
}
}
最后,EntryViewController:
class EntryViewController: NSViewController, EntryViewSelectionDelegate {
@IBOutlet weak var definitionField: NSTextField!
@IBOutlet weak var notesField: NSTextField!
@IBOutlet weak var entryField: NSTextField!
var entryObject: Entry!
override func viewDidLoad() {
super.viewDidLoad()
print("EVC loaded")
}
func sendSecondSelection(_ entrySelection: NSObject) {
self.entryObject = entrySelection as! Entry
print("EVC:", entryObject)
print(entryObject.headword)
// The Error gets thrown here:
entryField.stringValue = entryObject.headword
}
}
答案 0 :(得分:1)
您不需要委托/协议,因为有EntryViewController
(contentView
)的引用 - 用EntryViewController()
创建的实例不 viewDidLoad
中的实例化实例。
只需使用contentView
参考:
func sendSelection(_ entrySelection: NSObject) {
contentView?.sendSecondSelection(entrySelection)
}