Сбой приложения из-за привязки к представлению ячейки таблицы - PullRequest
0 голосов
/ 10 апреля 2020

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

Как вы можете видеть, это выглядит примерно так:

enter image description here

Проблема связана со столбцом Имя . В столбце имени для каждой строки у меня есть флажок и текстовое поле рядом. Это поможет вам получить более ясную идею:

enter image description here

Теперь я использую привязки, чтобы получить значение для каждого текстового поля. Однако, поскольку есть 2 представления (флажок и текстовое поле), которые должны быть привязаны к одному и тому же NSTableCellView, я возвращаю структуру из источника данных, содержащую 2 значения: строку для текстового поля (которое содержит файл / имя_каталога) и логическое значение для включения / выключения флажка.

Для обработки представления структуры (особенно его данных) я установил для его класса значение TorrentContent, которое определено следующим образом:

import Cocoa

struct Name {
    let value: String
    let enabled: Bool
}

class TorrentContent: NSOutlineView, NSOutlineViewDelegate, NSOutlineViewDataSource {
    var content: [TorrentContentItem]

    required init?(coder: NSCoder) {
        let srcDir = TorrentContentItem("src")

        let mainJava = TorrentContentItem("main.java")
        let mainCpp = TorrentContentItem("main.cpp")

        srcDir.children.append(mainJava)
        srcDir.children.append(mainCpp)

        content = [srcDir]

        super.init(coder: coder)

        delegate = self
        dataSource = self
    }

    func outlineView(_: NSOutlineView, isItemExpandable item: Any) -> Bool {
        if let _item = item as? TorrentContentItem {
            if _item.children.count > 0 {
                return true
            } else {
                return false
            }
        } else {
            return false
        }
    }

    func outlineView(_: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
        if item == nil {
            return content.count
        } else {
            if let _item = item as? TorrentContentItem {
                return _item.children.count
            }
        }

        return 0
    }

    func outlineView(_: NSOutlineView, child: Int, ofItem item: Any?) -> Any {
        if item != nil {
            if let _item = item as? TorrentContentItem {
                return _item.children[child]
            }
        }

        return content[child]
    }

    func outlineView(_: NSOutlineView, objectValueFor col: NSTableColumn?, byItem item: Any?) -> Any? {
        if item != nil, col != nil {
            if let _item = item as? TorrentContentItem {
                switch col!.title {
                case "Name":
                    return Name(value: _item.name, enabled: false)
                default:
                    return nil
                }
            }
        }

        return nil
    }
}

Я жестко запрограммировал данные, чтобы вам было легче понять, что происходит.

Сосредоточение внимания только на столбце имени, вот часть кода выше который имеет дело с этим:

func outlineView(_: NSOutlineView, objectValueFor col: NSTableColumn?, byItem item: Any?) -> Any? {
    if item != nil, col != nil {
        if let _item = item as? TorrentContentItem {
            switch col!.title {
            case "Name":
                return Name(value: _item.name, enabled: false)
            default:
                return nil
            }
        }
    }

    return nil
}

Как видите, он возвращает структуру Name, которая содержит значения для обоих представлений. Я жестко закодировал значение enabled в false только для целей тестирования.

Теперь, чтобы связать это со свойством value текстового поля, Я сделал это:

enter image description here

Мой лог c таков, поскольку objectValue является экземпляром Name struct, objectValue.value должно быть значением экземпляра структуры Name, который является строкой.

Я хочу связать включенным свойство флажка аналогично. Однако ни одна из привязок не работает. Они заставляют приложение взламывать sh. Это то, что XCode показывает мне после сбоя каждый раз, когда я пытаюсь просмотреть контурный вид во время выполнения:

enter image description here

Только получил "(lldb)" в console.

Что я делаю не так и как мне добиться того, чего я хочу? То есть установка значений свойств нескольких представлений из класса источника данных.

1 Ответ

1 голос
/ 10 апреля 2020

Привязки какао используют наблюдение значения ключа (KVO), и наблюдаемый объект должен быть KVO-совместимым. См. Использование наблюдения значения ключа в Swift .

Вы можете использовать наблюдение значения ключа только с классами, которые наследуются от NSObject.

Отметьте нужные свойства наблюдать с помощью наблюдения значения ключа с помощью атрибута @ obj c и модификатора dynamici c.

Решение A: Вернуть совместимый объект KVO из outlineView(_:objectValueFor:byItem:)

Решение B: Не используйте привязки какао. Создайте подкласс NSTableCellView и добавьте enabledCheckbox выход. Установите значения в outlineView(_:viewFor:item:).

...