Ответ 1
Я не тестировал и не пытался сделать следующее, но думал, что я все равно сделаю это.
Во-первых, управлять чем-либо сложным с помощью NSTableView или NSOutlineView с помощью NS * Controller является болезненным и жертвует точным контролем в обмен на простоту. Если вы обнаружите, что пытаетесь вести боевое поведение в этой ситуации, подумайте о том, чтобы реализовать собственный источник и делегировать протоколы (NSTableViewDataSource, NSTableViewDelegate или NSOutlineViewDataSource, NSOutlineViewDelegate) в своем собственном контроллере.
Во-вторых, комментарий Уоррена Бертона относительно увольнения уведомлений KVO уместен, так как вы должны сообщать ответственному диспетчеру (ваш NSTreeController) об изменениях, поскольку он контролирует (и наблюдает) эту коллекцию в любом случае. Более того, вы должны напрямую использовать методы NSTreeController add/insert/remove. То, как вы сейчас это делаете (ударяя всю структуру каждый раз, когда вы сбрасываете значение, затем reset позже), приведет к перезагрузке всего дерева. Поскольку контроллер наблюдает за этой коллекцией, он сообщает обрисованному контуру, чтобы обновить себя, возможно, чтобы сначала увидеть пустой контур, затем более расширенную версию контура, которая потеряет ваши пользовательские состояния расширения и т.д. Изменение модель через контроллер дерева позволит более разумные, более эффективные обновления вида.
В-третьих, вы могли бы рассмотреть возможность использования моего второго пункта выше, подклассифицируя NSTreeController и переопределяя методы add/insert/remove, чтобы сделать следующее:
- Запросить представление схемы для
-visibleRect
. - Вызовите super, чтобы начать изменение.
- Расскажите очертите схему
-scrollRectToVisible:
.
Возможно, вам придется задержать вызов на шаге 3, запланировав его в основном потоке (так происходит после текущей поездки через цикл запуска). Или, поочередно, замените шаг 3 с сохранением видимого прямоугольника где-нибудь и реализуя методы NSOutlineViewDelegate -outlineView:didAdd/RemoveRowView:forRow:
, чтобы проверить этот флаг THEN называть -scrollRectToVisible:
оттуда, если rect не равен нулю (запомните reset его NSZeroRect, чтобы он не пытается настраивать прокрутку каждый раз, когда строка контура добавляется или удаляется).
Clunky, но разумный (?) путь, который позволяет вам сохранять NSTreeController.
В-четвертых, в качестве альтернативы (и как я пойду) вы можете полностью удалить NSTreeController и реализовать протоколы NSOutlineViewDataSource (и NSOutlineViewDelegate) в своем собственном классе контроллера и позволить этому контроллеру напрямую обрабатывать добавление или удаление из вашей древовидной структуры. Затем он становится более чистым, так как вам не нужно беспокоиться о тайм-аутах KVO. При любом добавлении узлов вы можете заметить видимый прямоугольник, обновить представление схемы, а затем отрегулировать прокрутку в пределах одного и того же метода и пропустить цикл выполнения.
Я надеюсь, что это поможет и не слишком бессвязно.: -)