Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing NSAttributedString Core Data

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

like image 278
jodm Avatar asked Nov 24 '10 11:11

jodm


3 Answers

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 as Transformable. After you create the .h file, change the data type of attributedText from NSDictionary to NSAttributedString.

Now you can save the NSAttributedString in Core Data with no modification needed.

Recalling it is as easy as going:

myObject.attributedText

which will return your NSAttributedString!

Hope this helps someone.

like image 152
pob21 Avatar answered Nov 18 '22 11:11

pob21


Another idea would be to create a Custom Class of NSAttributedString and somewhere use enumerateAttributesInRange:options:usingBlock: to get all the attributes of the string and then save the NSDictionary 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:.

like image 41
Joshua Avatar answered Nov 18 '22 11:11

Joshua


In Xcode 10 with automatic code generation this is a lot simpler than the other suggestions.

  1. Select the name of the Attribute and open the Data Model inspector (Command+Option+3)
  2. Set Attribute Type to Transformable
  3. Set Custom Class to NSAttributedString

Screenshot of Xcode attribute inspector

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

like image 30
rodhan Avatar answered Nov 18 '22 12:11

rodhan