仅返回和导出 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 上设置双属性的值

核心数据迁移:无法将“NSManagedObject_MyType”类型的值转换为“MyModule.MyType”

xml 导出 php 代码仅返回 xml 文件的一个父级,我需要它们

核心数据 - NSManagedObject 返回 nil

如何更正错误“无法将 [NSManagedObject] 类型的值分配给 [String] 类型