-1

My app has the option to create several unique events whose values are saved in core data. When the table cell is pressed it loads the values of that event. What I need is to be able to export only that event information to NSData which can be exported then imported through a custom UTI. The code below works except it loads ALL events and exports the data. How can I make it so only the index path selected, with it's saved values, is exported and not all events in the entity?

-(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){}];
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Marc Matteo
  • 103
  • 2
  • 9

1 Answers1

0

Your exportclick method seems to have the object that you want to export, but then in exportContext:objectModel: you go ahead and fetch every object. It's exporting everything because that's what your code is written to do.

I'm not sure why you're doing a fetch request here. You already have the object you want to export, so what purpose does a fetch request serve? You already have the result. You also have code that knows how to look at an object and find the data you want to export. So, take the object you have, and take the code you have, and put the two together without doing a new fetch request.

Tom Harrington
  • 69,312
  • 10
  • 146
  • 170