Установите выход элемента в TableCellView в файле .xib на пользовательский подкласс NSTableCellView

#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. Не имеет значения, как вы их называете. Вы можете ссылаться на них из делегата, как я показываю в своем примере. Смотрите редактирование моего первоначального ответа