Подтвердить что ты не робот

Хранение основных данных 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 так сильно запутанным, что это противоречит сообщению об ошибке?

Просьба сообщить.

Спасибо Джеймс

4b9b3361

Ответ 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 с автоматической генерацией кода это намного проще, чем другие предложения.

  1. Выберите имя атрибута и откройте инспектор модели данных (Command + Option + 3)
  2. Установите Attribute Type в Transformable
  3. Установить 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