Прошу прощения, я относительно новичок в 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, когда пользователь вообще ничего не вводит. Я сталкиваюсь со следующими проблемами:
control(_ control: NSControl, textShouldEndEditing fieldEditor:
NSText) -> Bool
из NSTextFieldDelegate не вызывается, если пользователь действительно не набрал что-то в fieldEditor (не вызывается ни textShouldBeginEditing, это кажется очень старая история).
реализовать resignFirstResponder для NSTextView бесполезно, поскольку, как только TextView запрашивается для начала сеанса редактирования, он немедленно создает fieldEditor и отказывается от своего firstResponder. статус в пользу fieldEditor (также это, кажется, хорошо известное поведение)
Я установил ограничение для атрибута "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 ()