Я пытаюсь (неудачно) построить NSOutlineView с управлением TreeController. Я прошел кучу учебников, но все они предварительно загружают данные перед началом чего-либо, и это не сработает для меня.Использование NSTreeController с NSOutlineView
У меня есть простой класс для устройства:
import Cocoa
class Device: NSObject {
let name : String
var children = [Service]()
var serviceNo = 1
var count = 0
init(name: String){
self.name = name
}
func addService(serviceName: String){
let serv = "\(serviceName) # \(serviceNo)"
children.append(Service(name: serv))
serviceNo += 1
count = children.count
}
func isLeaf() -> Bool {
return children.count < 1
}
}
У меня также есть еще более простой класс для 'Сервис':
import Cocoa
class Service: NSObject {
let name: String
init(name: String){
self.name = name
}
}
Наконец, у меня есть ViewController:
class ViewController: NSViewController {
var stepper = 0
dynamic var devices = [Device]()
override func viewDidLoad() {
super.viewDidLoad()
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
@IBAction func addDeviceAction(_ sender: Any) {
let str = "New Device #\(stepper)"
devices.append(Device(name: str))
stepper += 1
print("Added Device: \(devices[devices.count-1].name)")
}
@IBAction func addService(_ sender: Any) {
for i in 0..<devices.count {
devices[i].addService(serviceName: "New Service")
}
}
}
Очевидно, у меня есть две кнопки, одна из которых добавляет «устройство» и добавляет «сервис» к каждому устройству.
То, что я не может, произойдут какие-либо из этих данных в NSOutlineView. Я установил объект в TreeController в контроллере свойства в режим: класс и класс: устройства, и без установки детей, граф, или свойство листьев я получаю (предсказуемо):
2017-01-04 17:20: 19.337129 OutlineTest [12550: 1536405] Внимание: [класс объекта: устройство] childrenKeyPath не может быть nil. Для устранения этого сообщения журнала, установите атрибут childrenKeyPath в Interface Builder
Если я затем установить свойство детей в «детские» дела идут очень плохо:
2017-01-04 17:23: 11.150627 OutlineTest [12695: 1548039] [Общие] [addObserver: forKeyPath: options: context:] не поддерживается. Ключевой путь: дети
Все, что я пытаюсь сделать, это настроить NSOutlineView принимать входные данные из NSTreeController так, что, когда новая «Device» добавляется к устройствам [] массив, он показывает в Просмотр структуры.
Если бы кто-нибудь мог указать мне в правильном направлении, я был бы очень благодарен.
Огромная благодарность Уоррену за чрезвычайно полезную работу. У меня есть (в основном) работа.Несколько вещей, которые я также необходимы, чтобы сделать, в дополнение к предложениям Уоррен:
Установите хранилищу для контроллера дерева
свяжи OutlineView к TreeController
свяжи Колонка в TreeController
Связать ячейку TableView с ячейкой таблицы (да, действительно)
После того, как все , что было сделано, я должен был играть с фактическим датасторе немного:
var name = "Bluetooth Devices Root"
var deviceStore = [Device]()
@IBOutlet var treeController: NSTreeController!
@IBOutlet weak var outlineView: NSOutlineView!
override func viewDidLoad() {
super.viewDidLoad()
deviceStore.append(Device(name: "Bluetooth Devices"))
self.treeController.content = self
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
@IBAction func addDeviceAction(_ sender: Any) {
if(deviceStore[0].name == "Bluetooth Devices"){
deviceStore.remove(at: 0)
}
Оказывается, корень не может быть ребенок-менее в начале, по крайней мере, насколько я могу сказать. Когда я добавлю ребенка, я могу удалить значение владельца места, и дерево, похоже, работает (в основном), как я хочу. Еще одна вещь, что я должен перезагрузить данные и повторного контура при изменении данных:
outlineView.reloadData()
outlineView.setNeedsDisplay()
Без этого ничего. У меня все еще нет правильного обновления данных (см. Комментарии ниже ответа Уоррена), но я почти там.
Вы можете попробовать установить массив в целом, вместо того, чтобы вставить, таким образом notifs КВО должен вызвать правильно. – Cristik
Я не могу этого сделать. Я действительно буду сканировать сетевые устройства и добавлять их по мере их обнаружения, как только это будет работать, и я не могу их предварительно загрузить и им придется вставлять их по мере их нахождения. – Davidgs
Вы можете сделать это с помощью неизменяемого массива вместо записи 'devices.append (Device (...))', вы пишете 'devices = devices + [Device (...)]', таким образом, значение 'devices' изменяется каждый раз при обнаружении нового устройства. – Cristik