NSOutlineView неожиданно обнаружил ноль - PullRequest
0 голосов
/ 01 марта 2020

Я пытаюсь сделать файловый браузер в моем приложении, которое открывается на боковой панели (с контроллером разделенного вида).

Источником является URL-адрес, полученный методом prepareForSegue в предыдущем viewController.

Каждый раз, когда загружается v c, я получаю фатальную ошибку:

Неустранимая ошибка: неожиданно обнаружен ноль при неявном развертывании Необязательное значение

Компилятор находит ошибку в том месте, где я объявляю:

outlineView.delegate = self outlineView.dataSource = self

Я попытался: 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

    }
}

'' '

1 Ответ

0 голосов
/ 01 марта 2020

Код prepareForSegue выявляет ошибку:

Вы устанавливаете echo в prepareForSegue. Это вызывает для вызова свойства наблюдателя didSet. Однако в этот момент представление еще не загружено, и принудительное развертывание типа приводит к сбою.

Решение состоит в том, чтобы переместить код из didSet в viewDidLoad и viewWillAppear и удалить наблюдатель свойства. Тем не менее, я рекомендую опциональное связывание window

var echo : Echo!

override func viewDidLoad() {
    super.viewDidLoad()
    setDelegatesAndDatasources()
    echo.checkFolderIntegrity()
    rootfileSystemItem = FileSystemItem(url: echo.url)
}

override func viewWillAppear(_ animated : Bool) {
    super.viewWillAppear(animated)
    if let window = self.view.window?.windowController as? WindowControllerEcho {
        window.directoryPath.url = echo.url
    }
}

Настройка delegate и dataSource достаточно один раз. Если вы используете раскадровку или Xib, наиболее удобный способ - соединить оба в Интерфейсном Разработчике.

...