Основные данные: отключить отмену для определенных атрибутов. Рекомендуемый подход не работает
У меня есть текстовое поле и флажок, подкрепленные основными данными. Изменения в флажке должны быть исключены из любых операций отмены / возврата.
Рекомендуемый подход (найденный при переполнении стека) - следующий фрагмент.
@IBAction func stateDidChange(sender: NSButton?)
{
//disable undo manager
context.processPendingChanges()
context.undoManager?.disableUndoRegistration()
//set value
let value = Bool(sender!.state == NSOnState)
<some NSManagedObject>.flag = value
//enable undo manager
context.processPendingChanges()
context.undoManager?.enableUndoRegistration()
}
Но это не работает. Когда пользователь
- редактирует текстовое поле,
- обновляет флажок,
- и продолжает редактировать текстовое поле,
затем изменения в флажке включаются в действие отмены.
Я тоже пробовал
NSNotificationCenter.defaultCenter().postNotificationName(NSUndoManagerCheckpointNotification, object: self.undoManager)
self.undoManager?.disableUndoRegistration()
//do work
NSNotificationCenter.defaultCenter().postNotificationName(NSUndoManagerCheckpointNotification, object: self.undoManager)
self.undoManager?.enableUndoRegistration()
Я даже попробовал это в подклассе NSManagedObject
var flag : Bool {
get {
self.willAccessValueForKey("flag")
let text = self.primitiveValueForKey("flag") as! Bool
self.didAccessValueForKey("flag")
return text
}
set {
let context = self.managedObjectContext!
context.processPendingChanges()
context.undoManager?.disableUndoRegistration()
self.willChangeValueForKey("flag")
self.setPrimitiveValue(newValue, forKey: "flag")
self.didChangeValueForKey("flag")
context.processPendingChanges()
context.undoManager?.enableUndoRegistration()
}
}
1 ответ
Не совсем ответ, но слишком длинный для комментария. Во-первых, я увидел, что подход, используемый, прекрасно работает, чтобы некоторые действия coreData не появлялись при отмене. Например, я использую его при создании новых объектов и установке начального состояния в коде. При таком подходе я разрешаю пользовательские правки объекта после этого, но их никогда нельзя отменить до исходного состояния объекта по умолчанию. В этом смысле совет, который вы получили, кажется правильным.
Тем не мение...
Я видел сообщения (но сам не проверял), что отмена CoreData ведет себя не так, как ожидалось. Я слышал, что вместо записи обратных операций для отдельных действий по изменению свойств вместо этого поддерживается стек состояний объектов. Если это правда, это может соответствовать вашему наблюдаемому поведению.
Рассмотрим объект с меткой = A и флажком = NO. Установите метку на B с разрешенной отменой. Состояние сейчас B & NO. Это можно откатить до A & NO. Теперь установите флажок ДА без отмены. Штат сейчас B & YES. Если отменить вызов сейчас, желаемое состояние будет A & YES, но это состояние никогда не существовало. Стек состояний для записанного
B & YES <- текущее состояние
B & NO - A & NO <- стек LIFO прошлых состояний
Однако, как я уже сказал, я на самом деле не проверял это. Некоторое время назад я провел несколько неубедительных тестов с хранилищем XML coreData, которое показало, что есть нечто большее, чем это. С другой стороны, я могу представить, что это может быть правдой для хранилища с резервированием SQLite, в зависимости от того, как CoreData использует базовую структуру SQL. Должен быть проверен.
Если это так, то можно предположить, что он реализован на объектной основе и что его можно обойти, поместив неотменяемые действия в дочерний объект один на один. Таким образом, состояние основного объекта остается непротиворечивым, в примере метка и ссылка на checkBoxObject. Тогда внутреннее состояние этого checkBoxObject может не иметь значения, так как ссылка в главном объекте неизменна. Но это должно быть проверено.
ОБНОВЛЕНИЕ В дополнение к моему первоначальному ответу, я потратил время на проверку представленной гипотезы и нашел ее верной. Похоже, что CoreData реализует отмену в виде LIFO-стека полных состояний объекта. Таким образом, невозможно иметь выборочную отмену определенных свойств внутри одного объекта.
Я также проверил вторую гипотезу о том, что эти стеки состояния LIFO являются объектами, и, таким образом, можно обойти эту проблему, поместив неотменяемые свойства в отдельный объект, связанный с 1 по 1 с исходным объектом. С этой настройкой достигается желаемое поведение.
Поведение идентично как для хранилищ CoreData с XML и SQLite.
Я также обнаружил, что для получения желаемого поведения код, модифицирующий свойства coreData, должен быть заключен в группу отмены, и что -processPendingChanges
должен вызываться в контексте управляемого объекта до закрытия группы отмены.