Используя выбор типа только для одного столбца с NSTableView в Swift - PullRequest
0 голосов
/ 30 апреля 2018

Я работаю в XCode 9.3, Swift, разрабатываю приложение для MacOS.

Я создал таблицу с двумя столбцами. Я хочу использовать выбор типа, который действует только на один столбец, поэтому, когда пользователь вводит первые несколько букв, он выбирает только в первом столбце, а не во 2-м столбце.

Документация Apple содержит пример в Objective-C здесь: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/TableView/RowSelection/RowSelection.html#//apple_ref/doc/uid/10000026i-CH6-SW1 но я не могу перевести это на Свифт. Я включил код таблицы ниже. Любая помощь будет принята с благодарностью.

extension ViewController: NSTableViewDataSource {
  func numberOfRows(in tableView: NSTableView) -> Int {
    return directoryItems?.count ?? 0
  }

  // Sorting.
  func tableView(_ tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor]) {
    guard let sortDescriptor = tableView.sortDescriptors.first else {
      return
    }

    if let order = Directory.FileOrder(rawValue: sortDescriptor.key!) {
      sortOrder = order
      sortAscending = sortDescriptor.ascending
      reloadFileList()
    }
  }

}

extension ViewController: NSTableViewDelegate {

  fileprivate enum CellIdentifiers {
    static let NameCell = "NameCellID"
    static let TimeCell = "TimeCellID"
    static let SizeCell = "SizeCellID"
  }

  func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {

    var image: NSImage?
    var text: String = ""
    var cellIdentifier: String = ""

    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = .long
    dateFormatter.timeStyle = .long

    guard let item = directoryItems?[row] else {
      return nil
    }

    if tableColumn == tableView.tableColumns[0] {
      image = item.icon
      text = item.name
      cellIdentifier = CellIdentifiers.NameCell

    } else if tableColumn == tableView.tableColumns[1] {
      let asset = AVAsset(url: item.url as URL)
      let audioTime = asset.duration
      text = audioTime.durationText
      cellIdentifier = CellIdentifiers.TimeCell

    } else if tableColumn == tableView.tableColumns[2] {
      text = item.isFolder ? "--" : sizeFormatter.string(fromByteCount: item.size)
      cellIdentifier = CellIdentifiers.SizeCell
    }

    if let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: cellIdentifier), owner: nil) as? NSTableCellView {
      cell.textField?.stringValue = text
      cell.imageView?.image = image ?? nil
      return cell
    }

    return nil
  }

}

1 Ответ

0 голосов
/ 30 апреля 2018

Ваша проблема двоякая:

Во-первых, вам нужно установить идентификатор для каждого из столбцов таблицы. Вы можете сделать это, выбрав столбец в Интерфейсном Разработчике, перейдя в Инспектор Идентификаций и установив для него некоторое строковое значение:

enter image description here

Как только вы это сделаете, создайте некоторые статические свойства для ссылки на эти идентификаторы (это не строго необходимо, поскольку вы, конечно, можете просто использовать rawValue для простого сравнения строк Objective-C, но новые идентификаторы Swift 4 являются типобезопасными и, следовательно, предпочтительными). Сделайте это так:

extension ViewController: NSTableViewDelegate {
    private struct TableColumns {
        static let foo = NSUserInterfaceItemIdentifier("Foo")
        static let bar = NSUserInterfaceItemIdentifier("Bar")
    }

    ...

}

Теперь вы можете использовать эти идентификаторы для ссылки на ваши столбцы, используя tableColumn(withIdentifier:) (или column(withIdentifier:), если вам нужен только номер столбца). Я рекомендую делать это везде, где вы ссылаетесь на них, в том числе в своем методе tableView(:viewFor:row:), поскольку то, как вы делаете это сейчас с tableView.tableColumns[0] и т. Д., Зависит от порядка столбцов, и если пользователь переупорядочивает их, он может вызвать неожиданное поведение. Использование идентификатора гарантирует, что вы всегда смотрите на столбец, на который, как вы думаете, вы смотрите.

В любом случае, после того как вы настроили свои идентификаторы, вы можете решить вторую проблему: вы используете неправильный метод делегата. Вместо tableView(:shouldTypeSelectFor:searchString:), который предназначен для перехвата этих вещей на уровне событий (то есть пользователь просто нажал клавишу. Должен ли я вообще вызывать систему выбора типа?), Используйте tableView(:typeSelectStringFor:row:). Этот метод позволяет вам вернуть строку, заданную механизму выбора типа для каждой комбинации строки / столбца в вашей таблице. Для тех, которые вы хотите игнорировать type-select, просто верните nil; в противном случае, верните строку, которую вы ожидаете ввести, чтобы выбрать эту конкретную строку. Итак, что-то вроде:

func tableView(_ tableView: NSTableView, typeSelectStringFor tableColumn: NSTableColumn?, row: Int) -> String? {
    if tableColumn?.identifier == TableColumns.foo {
        return directoryItems?[row].name
    } else {
        return nil
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...