在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实体中创建三个属性来实现此拆分:
- 影子NSString属性(’contentString’)
- 影子NSData属性(’contentAttributes’)
- ‘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问世以来,我现在可以在属性字典中使用NSForegroundColorAttributeName
, NSParagraphStyleAttributeName
, NSFontAttributeName
等,并且这些键伴随着可以存档的UIColor
, NSMutableParagraphStyle
和UIFont
等对象。