быстрое обнаружение события размытия для fieldEditor в NSTextView - PullRequest
0 голосов
/ 08 апреля 2020

Прошу прощения, я относительно новичок в swift (из Java / JavaScript background), поэтому вполне возможно, что я задаю тривиальный вопрос, но проблема, с которой я сталкиваюсь, кажется старой и, увы, , без ответа.

У меня есть (macOS AppKit, не iOS) TableView, заполненный сущностями CoreData (я использую NSArrayController, подключенный к managedObjectContext моего стека CD). Моя модель сущности имеет обязательный атрибут "name", для которого я не указал никакого значения по умолчанию в моем .xcdatamodel.

Когда я вставляю новую строку в мое табличное представление, я делаю textView «name» firstResponder, чтобы сообщить пользователю, что поле «name» вновь вставленной строки требует ввода, как это

@objc func contextDidChange(_ notification: Notification) {
    if (notification.userInfo![NSInsertedObjectsKey]) != nil {
        if ((notification.userInfo![NSInsertedObjectsKey] as! NSSet).anyObject() as? MyEntity) != nil {
            myEntityTableView.editColumn(0, row: myEntityArrayController.selectionIndex, with: nil, select: true)
        }
    }
}

Это работает нормально, теперь у меня есть fieldEditor, ожидающий ввода данных пользователем. Ситуация усложняется, когда я пытаюсь сделать код безошибочным, т. Е. Обрабатывать случай, когда редактор полей отказывается от статуса firstResponder, когда пользователь вообще ничего не вводит. Я сталкиваюсь со следующими проблемами:

  1. control(_ control: NSControl, textShouldEndEditing fieldEditor: NSText) -> Bool из NSTextFieldDelegate не вызывается, если пользователь действительно не набрал что-то в fieldEditor (не вызывается ни textShouldBeginEditing, это кажется очень старая история).

  2. реализовать resignFirstResponder для NSTextView бесполезно, поскольку, как только TextView запрашивается для начала сеанса редактирования, он немедленно создает fieldEditor и отказывается от своего firstResponder. статус в пользу fieldEditor (также это, кажется, хорошо известное поведение)

  3. Я установил ограничение для атрибута "name", чтобы сделать его уникальным, но это по-видимому, полностью игнорируется. Если я набираю одно и то же имя для двух строк, контекст сохраняется без сбоев (тогда как я получаю сообщение об ошибке, если поле «имя» пусто). На самом деле это «улов, который я пытаюсь поймать». Я хочу, чтобы пользователь набрал какой-то уникальный текст в столбце «имя» для вновь вставленной строки.

В Java или JavaScript это было бы очень просто: достаточно добавить прослушиватель событий «(on) blur», и вы сможете выполнить любую проверку.

Видимо, в AppKit все не так просто. Я искал способ перехватить действие resignFirstResponder для общего поля fieldEditor по умолчанию безуспешно.

Я думаю, что многие люди в моих сапогах.

Любой намек или Помощь будет принята с благодарностью

РЕДАКТИРОВАТЬ

В конце концов, мне удалось собрать воедино некоторый код для захвата becomeFirstResponder и resignFirstResponder редактора полей. Это включает создание подкласса NSTextField и превращение его в fieldEditor окна для соответствующей ячейки таблицы:

CustomFieldEditor.swift

class IngredientNameFieldEditor: NSTextView {

    @objc let managedObjectContext: NSManagedObjectContext? = (NSApp.delegate as! AppDelegate).sapoBasePersistentContainer?.viewContext

    private weak var lastError: NSError?

    override func becomeFirstResponder() -> Bool {
        lastError = nil
        return super.becomeFirstResponder()
    }

    override func resignFirstResponder() -> Bool {
        if managedObjectContext!.hasChanges {
            // Validation handling returning true or false
            // depending on the validation outcome
        }
        return super.resignFirstResponder()
    }
}

WindowDelegate.swift

class SettingsWindowController: NSWindowController {

    lazy var fieldEditor: IngredientNameFieldEditor? = {
        let fieldEditor = IngredientNameFieldEditor()
        fieldEditor.isFieldEditor = true
        return fieldEditor
    }()
}

extension SettingsWindowController: NSWindowDelegate {

    func windowWillReturnFieldEditor(_ sender: NSWindow, to client: Any?) -> Any? {
        if let client = client {
            if client is IngredientNameTextField {
                return fieldEditor
            }
        }
        return nil
    }
}

Что Я до сих пор не понимаю, почему ограничение «name» полностью игнорируется платформой при MO C save ()

...