存储NSAttributedString核心数据

时间:2010-11-24 11:26:47

标签: iphone objective-c core-data nsattributedstring

我正在尝试将NSAttributedString存储到Core Data SQL存储中。

我将属性设置为“可转换”,它是可选的,它不是瞬态的或索引的,并且值转换器名称设置为默认值“NSKeyedUnarchiveFromData”。在.xcdatamodel中生成了在.h:

中具有此功能的托管对象类
@property (nonatomic, retain) id Text; (I have tried changing id to NSAttributedString *Text)

这是在.m:

@dynamic Text;

我查看并将我的NSManagedObject的“。text”属性设置为属性字符串,然后在完成时执行:

NSError *error = nil;
[managedObjectContext save:&error];

此过程导致输出中出现此错误:

  

[NSCFType encodeWithCoder:]:   无法识别的选择器发送到实例   0xc04edb0由于终止应用程序   未捕获的异常   'NSInvalidArgumentException',原因:   ' * - [NSCFType encodeWithCoder:]:   无法识别的选择器发送到实例   0xc04edb0'

我已经检查了我存储到属性的类的类,它是NSAttributedString我也检查responsesToSelector @selector(:)并且这返回true,所以非常困惑,因为这与错误消息相反?

请告知。

由于 詹姆斯

7 个答案:

答案 0 :(得分:11)

对于遇到此问题的任何人,我找到了最简单的解决方案:

在Core Data中添加一个属性,我们称之为attributedText。然后将其类型定义为Transformable。创建.h文件后,将attributedText的数据类型从NSDictionary更改为NSAttributedString

现在,您可以将NSAttributedString保存在核心数据中,无需进行任何修改。

回顾它就像去一样容易:

myObject.attributedText

将返回NSAttributedString

希望这有助于某人。

答案 1 :(得分:6)

我正在查看 Apple开发者论坛并发现一个与此问题几乎完全相同的帖子,一个人已经这样做但很遗憾没有共享代码。他们所说的只是以下内容:

“在核心数据中,我在数据库中有一个可转换的,我是我自己的NSVauleTransformer。这是NSValueTransformer的子类,并从数据对象创建一个属性字符串,然后返回。

因此,我创建了一个名为PersistableAttributedString的类,它符合NSCoding。此类具有字符串和属性数组,并构建属性字符串。我还为符合NSCoding的可能文本属性创建了一个类。字符串和属性都符合NSCoding

班级NSAttributedString也符合NSCoding,但属性不是,这就是问题所在。“

希望可能有所帮助。

答案 2 :(得分:2)

另一个想法是创建一个NSAttributedString的自定义类,并在某处使用enumerateAttributesInRange:options:usingBlock:来获取字符串的所有属性,然后使用属性和范围保存NSDictionary核心数据以及剥夺其属性的属性字符串。

然后,当再次加载字符串时,您可以使用initWithString:attributes:将字典中的属性应用于属性字符串。

答案 3 :(得分:2)

在具有自动代码生成功能的Xcode 10中,这比其他建议要简单得多。

  1. 选择属性的名称并打开数据模型检查器( Command + Option + 3
  2. Attribute Type设置为Transformable
  3. Custom Class设置为NSAttributedString

Screenshot of Xcode attribute inspector

就是这样,现在您可以按照您的期望将数据保存在Swift代码中,例如:

detailItem.content = textView.attributedText

答案 4 :(得分:0)

这是给你带来悲伤的字体 - 一个CTDictionary是免费的桥接到NSDictionary,它实现了NSCoding所以编码应该很好。

你可能不得不自己处理这个字体:( - 这是一个很糟糕的做法。

1)不要存储NSAttributedString,而是将其分解并将每个组件放入一个数组中。

2)浏览数组 - 如果看到字体引用,则必须只存储重新创建此字体所需的信息 - 查看CTFontCopyFontDescriptor函数,CTFontDescriptorCopyAttribute函数应该让字体属性作为字符串。将所有这些放入NSDictionary中,它应该存储在核心数据中。

3)将此数组存储在核心数据中 - 希望数组中的所有项目都符合NSCoding,因此您应该没问题。

...

要重新创建字符串,当您从coredata加载时,如果您看到表示字体属性的NSDctionary,您应该能够重新创建fCTFontDescriptor并从中重新创建该字体。

然后,把你的绳子放回原处。

答案 5 :(得分:0)

我找到了一种在Swift 4中保存不使用头文件的属性文本的方法。我的核心数据存储包含一个名为" AttrNote"的实体。属性为" title"和"笔记"。 "标题"是"字符串"但"注意"属于"可转换的"。然后在视图输入/编辑完成的视图控制器中,我有以下保存按钮:

@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 :(得分:-1)

好的......某种突破虽然不是很好......

如果我们NSLog属性字符串,那么我们可以在那里看到它有NSFont和NSParagraphStyle。虽然这些不是NSFont和NSParagraphStyle在代码中这些是段落样式的CTFontRef和CT字典...这些不是NS对象虽然在NSLog中,它们作为这些输出,因此猜测这就是为什么我们不能在对象上执行“encodeWithCoder”选择器。

如果在代码中我们只做“NSFont;”编译器说“NSFont未声明”,那么我们可以做什么,因为我们只有CT功能?

正如我的同事在上面的评论中所说的那样,如果我们将“.text”属性设置为“NSAttrinutedString * string = [NSAttributedString alloc] initWithString:@”test“]它会保存很好,如果我们删除所有样式一个我们想要保存它也有效!

必须采用核心数据存储NSATTRIBUTED STRING的方式......不是吗?

任何想法都非常感激。

-JM