Какао: получить уведомление после редактирования текстовой ячейки (NSTextField) и начать редактирование текстовой ячейки после добавления ее в NSTableView в Swift 4? - PullRequest
0 голосов
/ 10 сентября 2018

Я сделал простую демонстрацию, используя TableView здесь: https://github.com/deadcoder0904/TableViewDemo

Я использовал По умолчанию модуль в качестве зависимости

Мой проект выглядит как

follow your dreams

Весь код в ViewController.swift выглядит следующим образом -

import Cocoa
import Defaults

extension Defaults.Keys {
    static let dreams = Defaults.Key<Array<String>>("dreams", default: [
        "Hit the gym",
        "Run daily",
        "Become a millionaire",
        "Become a better programmer",
        "Achieve your dreams"
        ])
}

class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {

    @IBOutlet weak var table: NSTableView!
    var dreams = defaults[.dreams]
    var selectedRow:Int = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        table.dataSource = self
        table.delegate = self
    }

    override var acceptsFirstResponder : Bool {
        return true
    }

    override func keyDown(with theEvent: NSEvent) {
        if theEvent.keyCode == 51 {
            removeDream()
        }
    }

    func tableViewSelectionDidChange(_ notification: Notification) {
        let table = notification.object as! NSTableView
        selectedRow = table.selectedRow
    }

    func numberOfRows(in tableView: NSTableView) -> Int {
        return dreams.count
    }

    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        let dream = table.makeView(withIdentifier: tableColumn!.identifier, owner: self) as! NSTableCellView
        dream.textField?.stringValue = dreams[row]

        return dream
    }

    @IBAction func addTableRow(_ sender: Any) {
        addNewDream()
    }

    @IBAction func removeTableRow(_ sender: Any) {
        removeDream()
    }

    func addNewDream() {
        dreams.append("Double Click or Press Enter to Add Item")
        table.beginUpdates()
        let last = dreams.count - 1
        table.insertRows(at: IndexSet(integer: last), withAnimation: .effectFade)
        table.scrollRowToVisible(last)
        table.selectRowIndexes([last], byExtendingSelection: false)
        table.endUpdates()
        saveDreams()
    }

    func removeDream() {
        if selectedRow >= dreams.count {
            selectedRow = dreams.count - 1
        }
        if selectedRow != -1 {
            dreams.remove(at: selectedRow)
            table.removeRows(at: IndexSet(integer: selectedRow), withAnimation: .effectFade)
        }
        saveDreams()
    }

    func saveDreams() {
        defaults[.dreams] = dreams
    }
}

Я хочу сделать 2 вещи -

  1. Получать уведомления после редактирования текстовой ячейки, чтобы я мог сохранить измененные данные с помощью модуля По умолчанию

  2. После добавления новых данных, нажав на знак плюс, он добавляет Двойной щелчок или нажмите Enter, чтобы добавить элемент , но я хочу добавить пустую строку, которую я могу сделать с "" но я также хочу, чтобы он был сфокусированным и редактируемым, чтобы пользователь мог начать вводить текст без необходимости двойного щелчка или нажатия Enter .

Мне также нужно решение в Swift 4, а не Objective-C. Как этого добиться?

1 Ответ

0 голосов
/ 10 сентября 2018

Используйте привязки какао, он очень мощный и экономит много стандартного кода.

Краткое руководство:

Редактировать: Чтобы в полной мере использовать KVC, источником данных должен быть подкласс NSObject с dynamic свойствами

  • Создать простой класс Dream (свойство description необязательно)

    class Dream : NSObject {
        @objc dynamic var name : String
        init(name : String) { self.name = name }
        override var description : String { return "Dream " + name }
    }
    
  • В контроллере представления объявляем массив источника данных

    var dreams = [Dream]()
    
  • и замените var selectedRow:Int = 0 на

    @objc dynamic var selectedIndexes = IndexSet()
    
  • Перейти к Интерфейсному Разработчику

    • Выберите представление таблицы, нажмите ⌥⌘7 , чтобы перейти к Инспектору привязок.
      Привязать Selection Indexes к View Controller Путь к ключу модели selectedIndexes.
      Нажмите ⌥⌘6 и подключите dataSource (путем перетаскивания) к контроллеру вида (enter image description here).

    • Выберите текстовое поле File 1 в Table Cell View в столбце таблицы. Самый простой способ - , щелкнуть в области текстового поля.
      Нажмите ⌥⌘7 и привяжите Value к Table Cell View Путь к ключу модели objectValue.name (! )

  • В контроллере представления заполните массив источника данных в viewDidLoad (я не знаю эту платформу, поэтому я опускаю его) и перезагрузите табличное представление.

    override func viewDidLoad() {
        super.viewDidLoad()
        let dreamNames = ["Hit the gym", "Run daily", "Become a millionaire", "Become a better programmer", "Achieve your dreams"]
        dreams = dreamNames.map{Dream(name: $0)}
        table.reloadData()         
    }
    
  • Удалить acceptsFirstResponder

  • Удалить tableViewSelectionDidChange
  • Удалить tableView:viewFor:row:
  • Добавить

    func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
        return dreams[row]
    }
    
  • Заменить addNewDream на

    func addNewDream() {
         let last = dreams.count
         dreams.append(Dream(name: "Double Click or Press Enter to Add Item"))
         table.insertRows(at: IndexSet(integer: last), withAnimation: .effectGap)
         table.scrollRowToVisible(last)
         table.selectRowIndexes([last], byExtendingSelection: false)
    
         saveDreams()
     }
    
  • Заменить removeDream() на

    func removeDream() {
         guard let selectedRow = selectedIndexes.first else { return }
         dreams.remove(at: selectedRow)
         table.removeRows(at: IndexSet(integer: selectedRow), withAnimation: .effectFade)
    
         saveDreams()
     }
    

Чтобы сохранить массив при последующем редактировании текста, необходимо реализовать метод делегата controlTextDidEndEditing(_:)

override func controlTextDidEndEditing(_ obj: Notification) {
    saveDreams()
}

и в Интерфейсном Разработчике подключите delegate текстового поля в табличном представлении к контроллеру представления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...