23

我正在尝试将 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 非常困惑,因为这与错误消息相反?

请指教。

谢谢詹姆斯

4

7 回答 7

11

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

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

现在您NSAttributedString无需修改​​即可保存在 Core Data 中。

回忆起来很容易:

myObject.attributedText

这将返回你的NSAttributedString

希望这可以帮助某人。

于 2013-12-18T16:42:00.617 回答
6

我正在查看Apple Developer Forums并发现一个与这个问题几乎完全相同的线程,一个人已经这样做了,但不幸的是没有分享代码。他们说的只有以下几点:

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

因此,我创建了一个符合要求PersistableAttributedString的类NSCoding。这个类有一个字符串和一个属性数组,并构建属性字符串。我还为可能的文本属性创建了一个NSCoding符合要求的类。字符串和属性一起都是NSCoding兼容的。

NSAttributedString也是NSCoding合规的,但属性不合规,这就是问题所在。”

希望这可能会有所帮助。

于 2010-11-24T17:11:31.527 回答
6

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

  1. 选择属性的名称并打开数据模型检查器( Command++ Option)3
  2. 设置Attribute TypeTransformable
  3. 设置Custom ClassNSAttributedString

Xcode 属性检查器截图

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

detailItem.content = textView.attributedText

于 2019-01-25T10:42:38.963 回答
2

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

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

于 2010-11-25T17:08:45.313 回答
0

它是让你悲伤的字体——CTDictionary 是免费桥接到实现 NSCoding 的 NSDictionary 的,所以应该可以很好地编码。

您可能必须自己处理字体:( - 这是一种糟糕的做法。

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

2)遍历数组——如果你看到字体引用,你必须只存储重新创建这个字体所需的信息——看看 CTFontCopyFontDescriptor 函数和 CTFontDescriptorCopyAttribute 函数应该让你以字符串的形式获取字体属性。将所有这些放入一个 NSDictionary 中,它应该可以很好地存储在核心数据中。

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

...

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

然后,把你的绳子放回去。

于 2010-11-24T15:36:45.830 回答
0

我找到了一种在不使用头文件的 Swift 4 中保存属性文本的方法。我的核心数据存储由一个名为“AttrNote”的实体组成,该实体具有“title”和“notes”的属性。“title”是“String”类型,但“notes”是“transformable”类型。然后在完成注释输入/编辑的视图控制器中,我有以下保存按钮:

@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

我可以保存属性文本,然后查看/编辑它。

于 2018-04-03T22:10:11.353 回答
-1

好吧……某种突破虽然不是很好……

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

如果在代码中我们只做“NSFont;” 编译器说“NSFont undeclared”那么我们能做什么,因为我们只有 CT 函数?

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

必须有一种方法可以将带有样式的 NSATTRIBUTED 字符串存储到核心数据中……不是吗?

任何想法都非常感谢。

-JM

于 2010-11-24T15:18:13.310 回答