仅返回和导出 NSManagedObject 的值
Posted
技术标签:
【中文标题】仅返回和导出 NSManagedObject 的值【英文标题】:Return and export only the values of NSManagedObject 【发布时间】:2018-03-09 03:19:06 【问题描述】:我的应用可以选择创建几个独特的事件,其值保存在核心数据中。当按下表格单元格时,它会加载该事件的值。我需要的是能够仅将该事件信息导出到 NSData 可以导出然后通过自定义 UTI 导入。下面的代码可以工作,除了它加载所有事件并导出数据。我怎样才能使它只导出选择的索引路径及其保存的值,而不是实体中的所有事件?
-(void)exportclick:(UIButton *)sender
mainview.hidden = YES;
NSInteger index = exportevent.tag;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
NSManagedObject *rawRecord = [self.fetchedResultsController objectAtIndexPath:indexPath];
TSPItem *record = [TSPItem castObject:rawRecord];
CDSurveyItem *surveyItem = [CDSurveyItem castObject:rawRecord];
[self setSelection:indexPath];
NSString *eventName = nil;
if (record.eventname)
eventName = record.eventname;
else if (surveyItem.eventname)
eventName = surveyItem.eventname;
[self setSelection:indexPath];
if (self.selection)
[self exportContext:self.managedObjectContext objectmodel:record];
- (void)exportContext:(NSManagedObjectContext *)context objectmodel:(NSManagedObject *)object
NSPersistentStoreCoordinator *coordinator = context.persistentStoreCoordinator;
NSManagedObjectModel *model = coordinator.managedObjectModel;
NSArray *entitites = [model entities];
NSMutableDictionary *data = [NSMutableDictionary dictionaryWithCapacity:[entitites count]];
for(NSEntityDescription *entity in entitites)
@autoreleasepool
NSArray *properties = [entity properties];
NSArray *allObjects = (
NSFetchRequest *fetchReq = [NSFetchRequest fetchRequestWithEntityName:[entity name]];
fetchReq.includesSubentities = NO; // important
[context executeFetchRequest:fetchReq error:nil];
);
NSMutableArray *items = [NSMutableArray arrayWithCapacity:[allObjects count]];
for(object in allObjects)
NSMutableDictionary *attrs = [NSMutableDictionary dictionaryWithCapacity:[entity.attributesByName count]];
NSMutableDictionary *relations = [NSMutableDictionary dictionaryWithCapacity:[entity.relationshipsByName count]];
for(NSPropertyDescription *property in properties)
// attributes
if([property isKindOfClass:[NSAttributeDescription class]])
// types that can be directly represented in JSON
NSAttributeType attrType = [(NSAttributeDescription *)property attributeType];
id val = [object valueForKey:[property name]];
if(val == nil)
[attrs setValue:[NSNull null] forKey:[property name]];
else if(attrType < NSDateAttributeType)
[attrs setValue:val forKey:[property name]];
else
if(attrType == NSDateAttributeType)
NSDate *dateVal = (NSDate *)val;
[attrs setValue:@kValueKey: [NSNumber numberWithInt:[dateVal timeIntervalSinceReferenceDate]],
kClassKey:[(NSAttributeDescription *)property attributeValueClassName]
forKey:[property name]];
else if(attrType == NSBinaryDataAttributeType)
NSData *dat = (NSData *)val;
NSString *klassName = [(NSAttributeDescription *)property attributeValueClassName];
if(klassName == nil) klassName = @"NSData"; // TODO: not tested whether this is needed.
[attrs setValue:@kValueKey:[dat base64EncodedString],
kClassKey:klassName
forKey:[property name]];
else if(attrType == NSTransformableAttributeType)
NSValueTransformer *transformer = (
NSString *transformerName = [(NSAttributeDescription *)property valueTransformerName];
(transformerName == nil ?
[[CodingValueTransformer alloc] init] :
[NSValueTransformer valueTransformerForName:transformerName]);
);
NSData *transformed = [transformer transformedValue:val];
[attrs setValue:@kValueKey:[transformed base64EncodedString] // a dictionary as value without a value for kClassKey implies a transformed val
forKey:[property name]];
else
NSLog(@"WARNING: Can't serialize %@ value to JSON.", [(NSAttributeDescription *)property attributeValueClassName]);
// relantionships
else if([property isKindOfClass:[NSRelationshipDescription class]])
NSRelationshipDescription *relationship = (NSRelationshipDescription *)property;
if(! [relationship isToMany]) // to-one
NSManagedObject *targetObject = [object valueForKey:[property name]];
if(targetObject == nil)
[relations setValue:[NSNull null] forKey:[property name]];
else
NSManagedObjectID *objID = [targetObject objectID];
if([objID isTemporaryID])
[context obtainPermanentIDsForObjects:@[targetObject] error:nil];
objID = [object objectID];
NSString *objIDString = [[objID URIRepresentation] path];
[relations setValue:@kItemKey:objIDString,
kEntityKey:[[relationship destinationEntity] name]
forKey:[property name]];
else // to-many
id<NSFastEnumeration> targetObjects = [object valueForKey:[property name]];
NSMutableArray *tempObjects = [NSMutableArray array];
for(NSManagedObject *targetObject in targetObjects)
if([targetObject.objectID isTemporaryID])
[tempObjects addObject:targetObject];
if([tempObjects count] > 0)
[context obtainPermanentIDsForObjects:tempObjects error:nil];
NSMutableArray *targetItems = [NSMutableArray array];
for(NSManagedObject *targetObject in targetObjects)
NSManagedObjectID *objID = [targetObject objectID];
NSString *objIDString = [[objID URIRepresentation] path];
[targetItems addObject:objIDString];
[relations setValue:@kItemsKey:targetItems,
kEntityKey:[[relationship destinationEntity] name]
forKey:[property name]];
NSString *objIDString = (
NSManagedObjectID *objID = [object objectID];
if([objID isTemporaryID])
[context obtainPermanentIDsForObjects:@[object] error:nil];
objID = [object objectID];
[[objID URIRepresentation] path];
);
[items addObject:@kObjectIDKey: objIDString,
kAttrsKey: attrs,
kRelationshipsKey: relations];
[data setObject:items forKey:[entity name]];
[context reset]; // save memory!
NSData *export = [NSJSONSerialization dataWithJSONObject:data options:0 error:nil];
MFMailComposeViewController *composeVC1 = [[MFMailComposeViewController alloc] init];
composeVC1 = [[MFMailComposeViewController alloc] init];
composeVC1.mailComposeDelegate = self;
[composeVC1 setSubject:[NSString stringWithFormat:@"Settings From %@ Event", [NSString stringWithFormat:@"tester_Export"]]];
[composeVC1 setMessageBody:[NSString stringWithFormat:@"Here are the event settings. Simply press on the attachment and then choose Open in my app"] ishtml:NO];
[composeVC1 addAttachmentData:export mimeType:@"application/octet-stream" fileName:[NSString stringWithFormat:@"tester_Export.myapp"]];
[self presentViewController:composeVC1 animated:NO completion:^(void)];
【问题讨论】:
你有没有尝试过,比如使用object
而不是获取所有对象?
在上面的代码中我不知道要更改什么来调用单个对象。
【参考方案1】:
您的exportclick
方法似乎有您要导出的对象,但随后在exportContext:objectModel:
中您继续获取每个对象。它导出所有内容,因为这就是您编写代码的目的。
我不确定您为什么要在此处执行提取请求。您已经有了要导出的对象,那么获取请求的目的是什么?你已经有了结果。您还拥有知道如何查看对象并找到要导出的数据的代码。因此,获取您拥有的对象,并获取您拥有的代码,然后将两者放在一起,而无需执行新的 fetch 请求。
【讨论】:
以上是关于仅返回和导出 NSManagedObject 的值的主要内容,如果未能解决你的问题,请参考以下文章
willSave 或 validateForUpdate 中的 NSManagedObject 动态属性更新
核心数据迁移:无法将“NSManagedObject_MyType”类型的值转换为“MyModule.MyType”