在CoreData中存储NSMutableAttributedString的简单方法

我正在尝试在CoreData存储NSMutableAttributedString ,但由于我的NSMutableAttributedString某些属性包含无法归档的Core Foundation对象,因此遇到了问题。 是否有一种简单的方法可以将此对象存储在CoreData中而无需手动执行某些杂乱的操作?

NSMutableAttributedString符合NSCoding ,这意味着它知道如何将自身转换为NSData或从NSData转换,并通过Core Data知道如何使用的协议来实现。

使属性“可转换”,然后只为其分配属性字符串。 由于它是可转换的,因此当您分配值时,Core Data将使用NSCoding将其转换为NSData ,并在读取时将其转换回属性字符串。

请注意,您将无法使用谓词来过滤此字段上的结果。 但存储和检索它很简单。

虽然上面的答案是正确的,但它有一个很大的缺点:

无法构建查询NSAttributedString对象内容的获取请求/谓词!

这样的谓词在执行时会导致exception:

 [NSPredicate predicateWithFormat:@"(content CONTAINS[cd] %@)", @"test"]]; 

要在Core Data中存储’fetchable’NSAttributedString,需要将NSAttributedString分为两部分:NSString端(可以获取)和NSData端,它存储属性。

可以通过在Core Data实体中创建三个属性来实现此拆分:

  1. 影子NSString属性(’contentString’)
  2. 影子NSData属性(’contentAttributes’)
  3. ‘undefined’瞬态归因(’内容’)

在自定义实体类中,“内容”将其创建的阴影和属性的更改归结为其阴影。

头文件:

 /** MMTopic */ @interface MMTopic : _MMTopic {} @property (strong, nonatomic) NSAttributedString* content; @end 

实施文件:

 /** MMTopic (PrimitiveAccessors) */ @interface MMTopic (PrimitiveAccessors) - (NSAttributedString *)primitiveContent; - (void)setPrimitiveContent:(NSAttributedString *)pContent; @end /** MMTopic */ @implementation MMTopic static NSString const* kAttributesDictionaryKey = @"AttributesDictionary"; static NSString const* kAttributesRangeKey = @"AttributesRange"; /* awakeFromFetch */ - (void)awakeFromFetch { [super awakeFromFetch]; // Build 'content' from its shadows 'contentString' and 'contentAttributes' NSString* string = self.contentString; NSMutableAttributedString* content = [[NSMutableAttributedString alloc] initWithString:string]; NSData* attributesData = self.contentAttributes; NSArray* attributesArray = nil; if (attributesData) { NSKeyedUnarchiver* decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:attributesData]; attributesArray = [[NSArray alloc] initWithCoder:decoder]; } if ((content) && (attributesArray.count)) { for (NSDictionary* attributesDictionary in attributesArray) { //NSLog(@"%@: %@", NSStringFromRange(((NSValue*)attributesDictionary[kAttributesRangeKey]).rangeValue), attributesDictionary[kAttributesDictionaryKey]); [content addAttributes:attributesDictionary[kAttributesDictionaryKey] range:((NSValue*)attributesDictionary[kAttributesRangeKey]).rangeValue]; } [self setPrimitiveContent:content]; } } /* content */ @dynamic content; /* content (getter) */ - (NSAttributedString *)content { [self willAccessValueForKey:@"content"]; NSAttributedString* content = [self primitiveContent]; [self didAccessValueForKey:@"content"]; return content; } /* content (setter) */ - (void)setContent:(NSAttributedString *)pContent { [self willChangeValueForKey:@"content"]; [self setPrimitiveValue:pContent forKey:@"content"]; [self didChangeValueForKey:@"content"]; // Update the shadows // contentString [self setValue:pContent.string forKey:@"contentString"]; // contentAttributes NSMutableData* data = [NSMutableData data]; NSKeyedArchiver* coder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; NSMutableArray* attributesArray = [NSMutableArray array]; [pContent enumerateAttributesInRange:NSMakeRange(0, pContent.length) options:0 usingBlock:^(NSDictionary* pAttributesDictionary, NSRange pRange, BOOL* prStop) { //NSLog(@"%@: %@", NSStringFromRange(pRange), pAttributesDictionary); [attributesArray addObject:@{ kAttributesDictionaryKey: pAttributesDictionary, kAttributesRangeKey: [NSValue valueWithRange:pRange], }]; }]; [attributesArray encodeWithCoder:coder]; [coder finishEncoding]; [self setValue:data forKey:@"contentAttributes"]; } @end 

现在可以通过以下方式获取:

 [NSPredicate predicateWithFormat:@"(contentString CONTAINS[cd] %@)", @"test"]]; 

虽然对NSAttributedString的任何访问都是这样的:

 textField.attributedText = pTopic.content; 

此处记录了在核心数据中使用“非标准属性”的规则: Apple文档

好吧,我不确定你要用属性字符串做什么,但如果它的格式化文本,那么你不能使用NSFont等。

看看http://ossh.com.au/design-and-technology/software-development ,我用uitextview和nstextview在格式化样式和图像上发布了一些东西,但主要是关于归因字符串。

这些东西都存储在核心数据中。

当iOS5 CoreText时我开始使用CoreText ,因此使用Core Foundation值作为属性。 但是我现在意识到,自从iOS6问世以来,我现在可以在属性字典中使用NSForegroundColorAttributeNameNSParagraphStyleAttributeNameNSFontAttributeName等,并且这些键伴随着可以存档的UIColorNSMutableParagraphStyleUIFont等对象。