Реализовать древовидное представление, подобное Finder, и представить его узлы с отложенной загрузкой с помощью NSOutlineview.

При реализации большого дерева файловой системы в NSOutlineview отсутствует уведомление о событии, когда пользователь щелкает значок треугольника со стрелкой вниз с левой стороны узла. Это очень важно при ленивой загрузке большого количества файловых узлов в узел каталога и представлении их в NSOutlineview. В противном случае разработчику придется загружать в него весь каталог, таким образом, загрузка заставит конечного пользователя ждать, это неприемлемо. Короче говоря, текущая версия NSOutlineview не может реализовать отложенную загрузку, вызванную этой проблемой. Кто-нибудь сталкивается с этой проблемой или имеет альтернативное решение для реализации древовидного представления, похожего на Finder, с помощью Cocoa NSOutlineview, любая помощь будет очень признательна.

Кроме того:

NSOutlineview не выдает событие layoutViewItemWillExpand при щелчке по значку, и по-прежнему не хватает информации, чтобы узнать, какой узел будет расширяться, даже если это сгенерированное событие, [NSOutlineview selectedRow] не может работать, потому что узел, который будет расширен, еще не выбран.


person Yeung    schedule 27.02.2020    source источник
comment
Взгляните на Пример кода TableViewPlayground.   -  person Willeke    schedule 27.02.2020
comment
Пожалуйста, опубликуйте свой код outlineViewItemWillExpand(_:). Пользовательская информация уведомления должна содержать элемент.   -  person Willeke    schedule 27.02.2020
comment
Спасибо @Willeke за образец ссылки, я это знаю, но суть в том, чтобы реализовать ленивую загрузку. Проблема в том, что даже метод layoutViewItemWillExpand() вызывается, но вы все равно не можете определить, к какому узлу принадлежит выбранный значок. В идеале, щелкнуть значок узла каталога, после чего каждый раз должен вызываться layoutViewItemWillExpand(), но на самом деле это не так.   -  person Yeung    schedule 27.02.2020
comment
Обратите внимание, г-н Виллеке, это щелчок по значку со стрелкой вниз слева, а не по узлу.   -  person Yeung    schedule 27.02.2020
comment
В TableViewPlayground ленивая загрузка реализуется моделью данных, а не outlineViewItemWillExpand(_:). Если вам нужна помощь в отладке outlineViewItemWillExpand(_:), опубликуйте, пожалуйста, минимально воспроизводимый пример.   -  person Willeke    schedule 28.02.2020
comment
Привет, мистер @Willeke, спасибо за ответ, но вы так и не поняли, в чем проблема. Вы можете щелкнуть значок со стрелкой вниз, после чего его узел будет развернут, в этот момент вызывается отложенная загрузка, но узел не может быть выбран щелчком. Такой проблемы нет, если дважды щелкнуть узел, а затем вызвать отложенную загрузку. Эту проблему можно решить, возможно, с помощью hittest, то есть проверить, какой значок был нажат и к какому узлу он принадлежит, но это увеличит сложность.   -  person Yeung    schedule 28.02.2020
comment
В чем проблема? Как реализовать ленивую загрузку? Или это outlineViewItemWillExpand(_:) не всегда вызывается, когда элемент расширяется? Или он получает элемент из уведомления?   -  person Willeke    schedule 28.02.2020


Ответы (1)


Я загружаю свои дочерние узлы в следующем вызове в NSOutlineViewDataSource:

func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
        guard let node = item as? Node else { return false }
        return node.children.count > 0
    }

Свойство children моего класса Node лениво и, следовательно, вынуждено загружаться здесь.

Этот метод вызывается только для узлов, которые видны в планировщике. Таким образом, вы загружаете только один слой перед видимым деревом. Треугольник раскрытия (стрелка расширения) будет виден, если дочерние элементы существуют.

Если у вас есть эффективный способ узнать количество дочерних элементов узла без их фактической загрузки, то может быть лучше просто вернуть количество дочерних элементов в outlineView(_: isItemExpandable:), а затем выполнить фактическую загрузку в outlineViewItemWillExpand(_:), как предложил Виллеке в комментариях.

person Giles    schedule 28.02.2020
comment
Или сделайте фактическую загрузку в outlineView(_:child:ofItem:). - person Willeke; 28.02.2020
comment
Да, мистер @Willeke, сделайте фактическую загрузку в layoutView(:child:ofItem:) работает, проблема решена, большое спасибо, но извините, я не могу отметить принятый ответ для вас. Заключение ------ 1, isItemExpandable() проста, если узел является каталогом, то вернуть YES. 2, в numberOfChildrenOfItem() получить количество дочерних узлов, если это каталог и при первой загрузке. 3, в layoutView(:child:ofItem:) сделайте то же самое, что и 2, чтобы реализовать ленивую загрузку. - person Yeung; 29.02.2020
comment
Спасибо, г-н @ Willeke, принять ваше предложение работает. но я не могу отметить принятый ответ для вас, не могли бы вы его сделать? - person Yeung; 01.03.2020