我正在尝试在侧面板(带有拆分视图控制器)中打开的应用中制作一个文件浏览器。
源是由上一个viewController中的prepareForSegue方法带来的URL。
每次vc加载时我都出现致命错误:
致命错误:在隐式展开一个可选值时意外发现nil
编译器将错误定位到我声明的位置:
outlineView.delegate =自我outlineView.dataSource =自我
我尝试过:1.通过代码,通过以下方式撤消和重做我所有的网点连接故事板2.通过情节提要通过代码重新连接委托和数据源3.我以为我的数据源方法可能有问题,我重写了5次4.我也尝试将setDelegatesAndDatasource方法也放入viewDidAppear中,认为这是视图生命周期的问题
我不知道发生了什么。感谢您的帮助。
'''
extension ViewControllerSource : NSOutlineViewDataSource, NSOutlineViewDelegate {
func setDelegatesAndDatasources(){
outlineView.delegate = self
outlineView.dataSource = self
}
// MARK: - NSOutlineView Datasource
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
if let fileSystemItem = item as? FileSystemItem {
return fileSystemItem.children.count
}
return 1
}
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
if let fileSystemItem = item as? FileSystemItem {
return fileSystemItem.children[index]
}
return rootfileSystemItem
}
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
if let fileSystemItem = item as? FileSystemItem {
return fileSystemItem.hasChildren()
}
return false
}
// MARK: - NSOutlineView Delegate
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
guard let colIdentifier = tableColumn?.identifier else { return nil }
if colIdentifier == NSUserInterfaceItemIdentifier(rawValue: "col1") {
let cellIdentifier = NSUserInterfaceItemIdentifier(rawValue: "cell1")
guard let cell = outlineView.makeView(withIdentifier: cellIdentifier, owner: nil) as? NSTableCellView else { return nil }
if let collection = item as? FileSystemItem {
cell.textField?.stringValue = collection.name ?? "Title not available"
cell.textField?.isEditable = false
cell.textField?.wantsLayer = true
cell.imageView?.image = collection.icon
// cell.textField?.delegate = self
} else {
cell.textField?.stringValue = "unknown item"
cell.textField?.isEditable = false
cell.textField?.wantsLayer = true
}
return cell
} else {
return nil
}
}
}
'''
这是主要的viewController文件:
'''
class ViewControllerSource: NSViewController {
@IBOutlet var outlineView: NSOutlineView!
var echo:Echo? {
didSet {
echo!.checkFolderIntegrity()
rootfileSystemItem = FileSystemItem(url: echo!.url)
let window = self.view.window?.windowController as! WindowControllerEcho
window.directoryPath.url = echo!.url
}
}
let propertyKeys: [URLResourceKey] = [.localizedNameKey, .effectiveIconKey, .isDirectoryKey, .typeIdentifierKey]
var rootfileSystemItem: FileSystemItem! {
didSet {
displayItems()
outlineView.reloadData()
}
}
// MARK: - Initialization
override func viewDidLoad() {
super.viewDidLoad()
setDelegatesAndDatasources()
}
func displayItems(){
for fileSystemItem in rootfileSystemItem.children as [FileSystemItem] {
print("item : \(fileSystemItem)")
for subItem in fileSystemItem.children as [FileSystemItem] {
print("\(fileSystemItem.name) - \(subItem.name)")
}
}
}
}
extension ViewControllerSource : EchoDelegate {
func didLoad(echo: Echo) {
self.echo = echo
}
}
'''
prepareForSegue
代码揭示了错误:
您正在echo
中设置prepareForSegue
。这导致调用属性观察器didSet
。但是,此时此视图尚未加载,并强制展开类型崩溃。
解决方案是将didSet
中的代码移到viewDidLoad
中并删除属性观察器。尽管如此,我还是建议选择绑定window
var echo : Echo!
override func viewDidLoad() {
super.viewDidLoad()
setDelegatesAndDatasources()
echo.checkFolderIntegrity()
rootfileSystemItem = FileSystemItem(url: echo.url)
if let window = self.view.window?.windowController as? WindowControllerEcho {
window.directoryPath.url = echo.url
}
}
一次设置delegate
和dataSource
就足够了。如果您使用情节提要或Xib,最方便的方法是在Interface Builder中将两者连接。