Хранение основных данных NSAttributedString
Я пытаюсь сохранить NSAttributedString в хранилище данных SQL.
У меня есть свойство, заданное как "трансформируемое", оно является необязательным и оно не является переходным или индексированным, а для имени преобразователя значения установлено значение по умолчанию "NSKeyedUnarchiveFromData". В .xcdatamodel и создан класс управляемого объекта, который имеет это в .h:
@property (nonatomic, retain) id Text; (I have tried changing id to NSAttributedString *Text)
и это в .m:
@dynamic Text;
Я просматриваю и устанавливаю свойство ".text" моего NSManagedObject в атрибутированную строку, а затем, когда закончил, я:
NSError *error = nil;
[managedObjectContext save:&error];
Это вызвано этой ошибкой на выходе:
[NSCFType encodeWithCoder:]: непризнанный селектор, отправленный в экземпляр 0xc04edb0 Завершение приложения из-за неперехваченное исключение "NSInvalidArgumentException", причина: '* - [NSCFType encodeWithCoder:]: непризнанный селектор, отправленный в экземпляр 0xc04edb0
Я проверил класс того, что я храню в свойстве, и это NSAttributedString
также проверяю responsesToSelector @selector(:)
, и это возвращает true так сильно запутанным, что это противоречит сообщению об ошибке?
Просьба сообщить.
Спасибо
Джеймс
Ответы
Ответ 1
Я проверял Форумы разработчиков Apple и нашел поток почти точно такой же, как этот вопрос, один человек сделал это, но, к сожалению, не разделил код. Все, что они сказали, было следующим:
"В базовых данных у меня есть трансформируемая база данных, и у меня есть собственный NSVauleTransformer. Это подкласс NSValueTransformer
и создает атрибутную строку из объекта данных и обратно.
Поэтому я создал класс PersistableAttributedString
, который соответствует NSCoding
. Этот класс имеет строку и массив атрибутов и строит присваиваемую строку. Я также создал класс для возможных текстовых атрибутов, который соответствует NSCoding
. Вместе строка и атрибуты соответствуют всем NSCoding
.
Класс NSAttributedString
также NSCoding
совместим, но атрибуты не являются, что проблема. "
Надеюсь, что это поможет.
Ответ 2
Для тех, кто испытывает эту проблему, я нашел самое простое решение:
В Core Data добавьте атрибут, позвоните ему attributedText
. Затем определите его тип как Transformable
. После создания файла .h измените тип данных attributedText
с NSDictionary
на NSAttributedString
.
Теперь вы можете сохранить NSAttributedString
в базовых данных без каких-либо изменений.
Вспомним, что это так же просто, как и вы:
myObject.attributedText
который вернет ваш NSAttributedString
!
Надеюсь, это поможет кому-то.
Ответ 3
Еще одна идея - создать пользовательский класс NSAttributedString
и где-нибудь использовать enumerateAttributesInRange:options:usingBlock:
, чтобы получить все атрибуты строки, а затем сохранить NSDictionary
с атрибутами и диапазонами в Core Data, а также с атрибутом строка лишена его атрибутов.
Затем, когда строка загружается снова, вы можете применить атрибуты, которые находятся в словаре, к атрибутной строке, используя initWithString:attributes:
.
Ответ 4
Это шрифт, который дает вам печаль - CTDictionary, является бесплатным мостом в NSDictionary, который реализует NSCoding, поэтому должен хорошо кодироваться.
Возможно, вам придется иметь дело с шрифтом самостоятельно:( - вот сосательный способ сделать это.
1) Вместо хранения NSAttributedString сломайте его и поместите каждый из его компонентов в массив.
2) Пройдите через массив - если вы увидите шрифт ref, вы должны сохранить только информацию, необходимую для воссоздания этого шрифта, - посмотрите на функцию CTFontCopyFontDescriptor, а функция CTFontDescriptorCopyAttribute должна позволить вам получить атрибуты шрифта в виде строки. Поместите все это в NSDictionary, который должен хранить в основных данных.
3) Сохраните этот массив в основных данных - надеюсь, все элементы в массиве будут совместимы с NSCoding, поэтому вы должны быть в порядке.
...
Чтобы воссоздать свою строку, когда вы загружаете из coredata, если вы видите NSDctionary, представляющий атрибуты шрифта, вы должны иметь возможность воссоздать fCTFontDescriptor и из этого шрифта.
Затем верните свою строку вместе.
Ответ 5
Я нашел способ сохранить приписанный текст в Swift 4, который не использует заголовочный файл. Мое хранилище основных данных состоит из сущности с именем "AttrNote" с атрибутами "title" и "notes". "title" имеет тип "String", но "notes" имеет тип "transmable". Затем в контроллере представления, где выполняется запись/редактирование заметки, у меня есть следующее для кнопки сохранения:
@IBAction func saveBtn(_ sender: Any) {
var note: AttrNote!
//other code
if let title = titleTextField.text {
note.title = title
}
if let noteText = notesTextView.attributedText {
note.notes = noteText
}
И функция, которая вызывается для загрузки данных, имеет следующее:
func loadNoteData() {
if let note = noteToEdit {
titleTextField.text = note.title
notesTextView.attributedText = note.notes as! NSAttributedString
}
}
И у меня есть следующее в ViewDidLoad, который позволяет опции форматирования B/I/U появляться с выделением текста:
notesTextView.allowsEditingTextAttributes=true
Я могу сохранить приписанный текст, а затем просматривать/редактировать его позже.
Ответ 6
В Xcode 10 с автоматической генерацией кода это намного проще, чем другие предложения.
- Выберите имя атрибута и откройте инспектор модели данных (Command + Option + 3)
- Установите
Attribute Type
в Transformable
- Установить
Custom Class
в NSAttributedString
![Screenshot of Xcode attribute inspector]()
И вот, теперь вы можете просто сохранить свои данные в своем коде Swift, как вы ожидаете, например:
detailItem.content = textView.attributedText
Ответ 7
ОК... Какой-то прорыв, хотя и не хороший...
Если мы NSLog присваиваемой строки, то мы можем видеть, что там есть NSFont и NSParagraphStyle. Хотя это НЕ NSFont и NSParagraphStyle в коде, это CTFontRef и CT словари стилей абзацев... Это не NS-объекты, хотя в NSLog они выводятся как эти и поэтому предполагают, что мы не можем выполнить селектор "encodeWithCoder" на объекте.
IF в коде, который мы просто делаем "NSFont"; компилятор говорит "NSFont uneclared", так что мы можем сделать, поскольку у нас есть только функции CT?
Как сказал мой коллега в комментариях выше, если мы установили свойство ".text" как "NSAttrinutedString * string = [NSAttributedString alloc] initWithString: @" test "], это сэкономит штраф, и если мы удалим все стили из один, который мы хотим сохранить, также работает!
ТАК ДОЛЖНО БЫТЬ СПОСОБОМ ХРАНЕНИЯ НАТЯЖЕННОЙ СТРОКИ С СТИЛИМИРОВАНИЕМ В ОСНОВНЫЕ ДАННЫЕ... НЕТ?
Любые идеи получили высокую оценку.
-JM