#swift #macos #nstableview #iboutlet #nstablecellview
#swift #macos #nstableview #iboutlet #nstablecellview
Вопрос:
Я хочу заполнить свой NSTableView
контентом. В строке ячейки таблицы находятся 3 элемента (2 NSTextFields
и 1 NSImageView
). Для этого я создал пользовательский, NSTableCellView
где я хочу установить @IBOutlets
из 3 элементов, чтобы установить там значение для них. Но когда я пытаюсь установить ссылочные выходы, единственным вариантом является создание действия.
Когда я пытаюсь записать, @IBOutlet weak var personName: NSTextfield
а затем установить ссылки, я не могу, потому что «xcode не может найти класс в текущей рабочей области»
Когда я создаю NSTableView
внутри main.storyboard, я могу установить ссылки на выходы. Итак, в чем разница между .storyboard и .xib?
Когда я пытаюсь подключить @IBOutlet к элементу «Имя пользователя»,
Мой NSViewController (владелец .xib)
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
@IBOutlet weak var tableView: NSTableView! //ref to tableView in xib
var persons:[Person] = [] //content to fill tableview
override func viewDidLoad() {
super.viewDidLoad()
persons.append(Person(name: "John", age: 23, piRef: "/Users/xy/Desktop/profilePic.png"))
persons.append(Person(name: "Marie", age: 26, piRef: "/Users/xy/Desktop/profilePic.png"))
tableView.delegate = self
tableView.dataSource = self
}
func numberOfRows(in tableView: NSTableView) -> Int {
return persons.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let tableCellView:personTableCell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "defaultRow"), owner: self) as! personTableCell
//NSTableColumn in xib has id "defaulRow"
if let person:Person = persons[row] {
tableCellView.setPerson(person: person) //call method inside NSTableCellView-subclass to set item values
}
return tableCellView
}
}
Пользовательский подкласс NSTableCellView («personTableCell»)
class personTableCell: NSTableCellView {
var person:Person! = nil
//here should be:
//@IBOutlet weak var personName: NSTextField!
//@IBOutlet weak var personAge: NSTextField!
//@IBOutlet weak var personImg: NSImageView!
func setPerson(person: Person) {
self.person = person
self.personName = person.name
self.personAge = person.age
self.personImg = NSImage(byReferencingFile: person.profileImgRef)
}
}
Я хочу иметь возможность добавлять ссылки на выход элемента в мой подкласс NSTableCellView.
Ответ №1:
Мне кажется, вы делаете это сложнее, чем это должно быть. makeView предоставляет вам ссылку на ячейку. Таким образом, вы можете получить доступ к его элементам напрямую. Нет необходимости в выходах (именно поэтому Xcode не будет создавать их для вас.)
Я не могу достаточно хорошо прочитать ваши скриншоты, чтобы рассказать, как определяются текстовые поля (старые глаза), поэтому я могу привести вам только общий пример из рабочей демонстрации пользовательского класса cell:
class DIYTableViewDelegate: NSObject, NSTableViewDelegate {
var count = 0 // counts the number of views actually created
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let id = tableColumn!.identifier
var view = tableView.makeView(withIdentifier: id, owner: nil) as? CustomTableCellView
if view == nil {
view = createCell(id)
count = 1
}
view!.textField!.stringValue = "(id.rawValue) (row) (view!.count) (count)"
view!.count = 1
return view
}
}
Кроме того, в Swift принято писать заглавными буквами первые буквы типов (классы, структуры, перечисления, протоколы) и методы и свойства в нижнем регистре. Это не влияет на то, как компилируется ваш код, но помогает другим Swifties читать его.
Вот еще один пример, который может помочь:
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
guard let vw = tableView.makeView(withIdentifier: tableColumn!.identifier, owner: self) as? CustomTableCellView else { return nil }
vw.textField?.stringValue = String(pictures[row].dropLast(4))
vw.imageView?.image = NSImage(named: pictures[row])
return vw
}
Комментарии:
1. если бы у меня было 2 текстовых поля в 1 ячейке, как я мог бы установить значение конкретного
2. Было бы полезно, если бы я действительно мог увидеть, как вы определяете поля в раскадровке. Извините, я не могу прочитать скриншот.
3. Их идентификаторами являются «fileName» и «fileImg» или есть другой способ их определения?
4. Не имеет значения, как вы их называете. Вы можете ссылаться на них из делегата, как я показываю в своем примере. Смотрите редактирование моего первоначального ответа