我正在尝试将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,所以非常困惑,因为这与错误消息相反?
请告知。
由于 詹姆斯
答案 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中,这比其他建议要简单得多。
Attribute Type
设置为Transformable
Custom Class
设置为NSAttributedString
就是这样,现在您可以按照您的期望将数据保存在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