存储 NSAttributedString 核心数据
我正在尝试将 NSAttributedString 存储到核心数据 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];
以下 操作: through 导致输出中出现此错误:
[NSCFTypeencodeWithCoder:]: 无法识别的选择器发送到实例 0xc04edb0 由于以下原因终止应用程序 未捕获的异常 'NSInvalidArgumentException',原因: '* -[NSCFTypeencodeWithCoder:]: 无法识别的选择器发送到实例 0xc04edb0'
我已经检查了我要存储到属性中的内容的类,它是 NSAttributedString
我还检查了 responsesToSelector @selector(:)
并且这返回 true 所以非常困惑这与错误消息相反?
请指教。
谢谢 詹姆斯
I am trying to store an NSAttributedString to a Core Data SQL store.
I have the property set as a "transformable", it is optional and it is NOT transient or indexed and the value transformer name is set to default "NSKeyedUnarchiveFromData". In the .xcdatamodel and generated the managed object class which has this in the .h:
@property (nonatomic, retain) id Text; (I have tried changing id to NSAttributedString *Text)
and this in the .m:
@dynamic Text;
I look through and set the ".text" property of my NSManagedObject to the attributed string then when completed I do:
NSError *error = nil;
[managedObjectContext save:&error];
This through is causing this error in the output:
[NSCFType encodeWithCoder:]:
unrecognized selector sent to instance
0xc04edb0 Terminating app due to
uncaught exception
'NSInvalidArgumentException', reason:
'* -[NSCFType encodeWithCoder:]:
unrecognized selector sent to instance
0xc04edb0'
I have checked the class of what I am storing to the property and it is NSAttributedString
also I check responsesToSelector @selector(:)
and this returns true so very confused as this is contrary to the error message?
Please advise.
Thanks
James
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
对于遇到此问题的任何人,我找到了最简单的解决方案:
在 Core Data 中添加一个属性,我们将其称为
attributedText
。然后将其类型定义为Transformable
。创建 .h 文件后,将attributedText
的数据类型从NSDictionary
更改为NSAttributedString
。现在您可以将
NSAttributedString
保存在 Core Data 中,无需任何修改。回忆起来就像走一样简单:
这将返回您的
NSAttributedString
!希望这对某人有帮助。
For anyone experiencing this problem I found the easiest solution:
In Core Data add an attribute, let's call it
attributedText
. Then define its type asTransformable
. After you create the .h file, change the data type ofattributedText
fromNSDictionary
toNSAttributedString
.Now you can save the
NSAttributedString
in Core Data with no modification needed.Recalling it is as easy as going:
which will return your
NSAttributedString
!Hope this helps someone.
我在检查Apple开发者论坛并发现了一个与这个问题几乎完全相同的帖子,一个人已经做到了这一点,但不幸的是没有分享代码。他们所说的只是以下内容:
“在 Core Data 中,我在数据库中有一个可转换对象,并且我使用自己的 NSVauleTransformer。这是 NSValueTransformer 的子类,并从数据对象创建一个属性字符串并返回。
因此,我创建了一个名为
PersistableAttributedString
的类,它符合NSCoding
规范,该类具有一个字符串和一个属性数组,并构建了属性字符串。符合NSCoding
的文本属性 字符串和属性都符合NSCoding
类
NSAttributedString
也是NSCoding
。 code> 兼容,但属性不兼容,这就是问题所在。”希望这可能有所帮助。
I was checking the Apple Developer Forums and found a thread almost exactly the same as this question, one person had done this but unfortunately did not share the code. All they said was the following:
"In Core Data i have an transformable in the database and i us my own NSVauleTransformer. This is a subclass of
NSValueTransformer
and creates an attributed string from the data object and back.Therefore i created a class called
PersistableAttributedString
which isNSCoding
compliant. This class has a string and an array of attributes and builds the attributed string. I also created a class for the possible text attributes which isNSCoding
compliant. Together the string and the attributes are allNSCoding
compliant.The class
NSAttributedString
is alsoNSCoding
compliant, but the attributes are not, that's the problem."Hope that might help.
在具有自动代码生成功能的 Xcode 10 中,这比其他建议简单得多。
属性类型
将Transformable
自定义类
为NSAttributedString
就是这样,现在您可以将数据保存在 Swift 中代码如您所料,例如:
detailItem.content = textView.attributedText
In Xcode 10 with automatic code generation this is a lot simpler than the other suggestions.
Attribute Type
toTransformable
Custom Class
toNSAttributedString
And that's it, now you can just save your data in your Swift code as you'd expect, e.g.:
detailItem.content = textView.attributedText
另一个想法是创建一个 NSAttributedString 的自定义类,并在某个地方使用 enumerateAttributesInRange:options:usingBlock: 来获取字符串的所有属性,然后保存 NSDictionary 包含核心数据中的属性和范围以及删除其属性的属性字符串。
然后,当再次加载字符串时,您可以使用
initWithString:attributes:
将字典中的属性应用到属性字符串。Another idea would be to create a Custom Class of
NSAttributedString
and somewhere useenumerateAttributesInRange:options:usingBlock:
to get all the attributes of the string and then save theNSDictionary
with the attributes and ranges in to Core Data aswell as the attributed string stripped of it's attributes.Then when the string is loaded again you could apply the attributes that are in the dictionary to the attributed string using
initWithString:attributes:
.正是这种字体让你感到悲伤——CTDictionary 是免费桥接到 NSDictionary 的,NSDictionary 实现了 NSCoding,所以应该可以很好地编码。
您可能必须自己处理字体:( - 这是一种糟糕的方法。1
) 不要存储 NSAttributedString,而是将其分解并将其每个组件放入一个数组中。
2) 遍历数组 - 如果您看到字体引用,则必须仅存储重新创建此字体所需的信息 - 查看 CTFontCopyFontDescriptor 函数,CTFontDescriptorCopyAttribute 函数应该让您以字符串形式获取字体属性。将所有这些放入 NSDictionary 中,该字典应该很好地存储在核心数据中。
3)将此数组存储在核心数据中 - 希望数组中的所有项目都符合 NSCoding 标准,所以应该没问题。
...
要重新创建字符串,当您从 coredata 加载时,如果您看到表示字体属性的 NSDctionary,您应该能够重新创建 fCTFontDescriptor 并从中重新创建字体。
然后,将绳子放回原处。
It's the font that's giving you grief - a CTDictionary is toll-free bridged to NSDictionary which implements NSCoding so should encode fine.
You might have to deal with the font yourself :( - here's a sucky way of doing it.
1) Instead of storing the NSAttributedString, break it down and put each of it's components into an array.
2) Go through the array - if you see font ref you must store just the information required to re-create this font - have a look at the CTFontCopyFontDescriptor function and the CTFontDescriptorCopyAttribute function should let you get font attributes as a string. Put all these into a NSDictionary which should store in core data fine.
3) Store this array in core data - hopefully all the items in the array will be NSCoding compliant so you should be fine.
...
To recreate your string, when you load from coredata, if you see an NSDctionary representing font attributes you should be able to re-create the fCTFontDescriptor and from that the font.
Then, put your string back together.
好吧...某种突破,虽然不是一个好的突破...
如果我们 NSLog 属性字符串,那么我们可以看到其中有 NSFont 和 NSParagraphStyle。虽然这些在代码中不是 NSFont 和 NSParagraphStyle,但它们是 CTFontRef 和段落样式的 CT 词典...这些不是 NS 对象,尽管在 NSLog 中它们输出为这些对象,因此猜测这就是为什么我们无法在对象上执行“encodeWithCoder”选择器的原因。
如果在代码中我们只执行“NSFont;”编译器说“NSFont 未声明”,那么我们只有 CT 函数,我们能做什么呢?
正如我的同事在上面的评论中所说,如果我们将“.text”属性设置为“NSAttrinulatedString *string = [NSAttributedString alloc] initWithString:@"test"],它会保存得很好,如果我们从我们想要的样式中删除所有样式保存它也有效!
必须有一种方法可以将 NSATTRIBUTED 字符串存储到核心数据中...不?
非常感谢
-JM 。
OK... Some kind of break through although not a good one...
If we NSLog the attributed string then we can see in there it has NSFont and NSParagraphStyle in. Although these are NOT NSFont and NSParagraphStyle in the code these are CTFontRef and CT Dictionaries of paragraph styles... These are not NS objects although in NSLog they output as these and therefore guess that is why we can not perform the "encodeWithCoder" selector on the object.
IF in the code we just do "NSFont;" the compiler says "NSFont undeclared" so what can we do as we only have the CT functions?
As my colleague said in the comments above if we set the ".text" property to just "NSAttrinutedString *string = [NSAttributedString alloc] initWithString:@"test"] it saves fine and if we remove all the styling from the one we WANT to save it also works!
THERE MUST BE A WAY OF STORING NSATTRIBUTED STRING WITH STYLING INTO CORE DATA... NO?
Any ideas greatly appreciated.
-JM
我找到了一种在 Swift 4 中保存属性文本的方法,该方法不使用头文件。我的核心数据存储由一个名为“AttrNote”的实体组成,其属性为“标题”和“注释”。 “title”的类型为“String”,但“notes”的类型为“transformable”。然后在完成注释输入/编辑的视图控制器中,我有以下保存按钮:
调用加载数据的函数有以下内容:
我在 ViewDidLoad 中有以下内容,可以启用 B/I/U选择文本时显示的格式选项:
我可以保存属性文本,然后稍后查看/编辑它。
I found a way to save attributed text in Swift 4 that does not use a header file. My Core Data store consists of an entity called "AttrNote" with attributes of "title" and "notes". "title" is of type "String" but "notes" is of type "transformable". Then within the view controller where note entry/editing is done I have the following for the save button:
And the function that is called to load the data has the following:
And I have the following in ViewDidLoad that enables the B/I/U formatting options to appear with the selection of text:
I am able to save attributed text and then view/edit it later.