Question

I have a fairly basic app that takes the input from one view controller, and saves it, allowing the user to see the data on a separate Table View Controller. The data being saved is nothing more than several strings, and one image. Everything has been working perfectly until all-of-a-sudden, my images no longer appear in the TableViewController until after the app has been reset.

My Table View is set up with the correct number of sections and the correct number of cells, and the data show in them is as it should be, the exception being only the image.

Here is my "Save to CoreData" code:

- (IBAction)saveTarget:(id)sender {
    //Only save if there is an image other than the stock photo
    if (self.transfer.targetImage) {

        //Grab the main ManagedObjectContext from the AppDelegate
        sTCAppDelegate *appDelegate =[[UIApplication sharedApplication] delegate];
        NSManagedObjectContext *context =[appDelegate managedObjectContext];
        //Get the Target model from CoreData
        [self setTarget:[NSEntityDescription insertNewObjectForEntityForName:@"TargetData" inManagedObjectContext:context]];

        //Save the strings from the child view controller
        self.target.weaponData = self.transfer.weaponData;
        self.target.bulletType = self.transfer.bulletType;
        self.target.stanceType = self.transfer.stanceType;
        self.target.distanceData = self.transfer.distanceData;
        self.target.targetNotes = self.transfer.targetNotes;
        self.target.sightType = self.transfer.sightType;
        self.target.scoreData = self.transfer.scoreData;

        //Save the image from the child view controller
        self.target.targetImage = self.transfer.targetImage;

        //Save the range data from the preset values
        self.target.rangeName = self.name;
        self.target.rangeStreet = self.street;
        self.target.rangeCity = self.city;
        self.target.rangeState = self.state;

        //Set a date property to use for organizing by most recently saved
        NSDate *date = [NSDate date];
        NSDate *dateMod = [self dateAtBeginningOfDayForDate:date];
        self.target.timeStamp = dateMod;
        //Save a more user-friendly date string
        self.target.formattedTimeStamp = [self.dateFormatter stringFromDate:dateMod];

        //Save to context
        NSError *error = nil;
        if ( ![context save:&error] ){
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }

        //Pop to main menu
        [self.navigationController popToRootViewControllerAnimated:YES];

        //set images back to nil for next time AddTarget is opened
        self.target.targetImage = nil;
        NSLog(@"Data Saved");
    }
    //Return alert if user has not entered a photo
    else{
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"We're Sorry!" message:@"You must enter at least a photo to save target data." delegate:nil cancelButtonTitle:@"Okay" otherButtonTitles:nil];
        [alert show];
    }
}

Here is my "Retrieve from CoreData code":

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    NSLog(@"number of sections:%lu",(unsigned long)[[self.fetchedResultsController sections] count]);
    return [[self.fetchedResultsController sections] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    NSLog(@"%lu", (unsigned long)[sectionInfo numberOfObjects]);
    return [sectionInfo numberOfObjects];
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    return [[[sectionInfo objects] objectAtIndex:0] formattedTimeStamp];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    NSLog(@"Ran Cell Configure");
    [self configureCell:cell atIndexPath:indexPath];
    // Configure the cell...

    return cell;
}

-(void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath{

    TargetData *target = [self.fetchedResultsController objectAtIndexPath:indexPath];
    UIImage *image = [self resizeImage:[UIImage imageWithData:target.targetImage] toWidth:50 andHeight:50];
    cell.imageView.image = image;
    cell.textLabel.text = [NSString stringWithFormat:@"%@", target.scoreData];
    cell.detailTextLabel.text = target.weaponData;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        sTCAppDelegate *appDelegate =[[UIApplication sharedApplication] delegate];
        NSManagedObjectContext *context =[appDelegate managedObjectContext];

        [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];

        NSError *error;
        if (![context save:&error]) {
            /*
             Replace this implementation with code to handle the error appropriately.

             abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
             */
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}
#pragma mark- Fetched Objects Delegate

- (NSFetchedResultsController *)fetchedResultsController {
    if (_fetchedResultsController != nil)
    {
        return _fetchedResultsController;
    }
    sTCAppDelegate *appDelegate =[[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *context =[appDelegate managedObjectContext];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"TargetData" inManagedObjectContext:context];

    [fetchRequest setEntity:entity];
    [fetchRequest setFetchBatchSize:0];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];

    [fetchRequest setSortDescriptors:sortDescriptors];

    NSFetchedResultsController *aFetchedRequestsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"timeStamp" cacheName:nil];
    aFetchedRequestsController.delegate = self;
    self.fetchedResultsController = aFetchedRequestsController;

    NSError *error = nil;

    if (![self.fetchedResultsController performFetch:&error])
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _fetchedResultsController;
}

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                          withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                          withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath {

    UITableView *tableView = self.tableView;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath]
                    atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}
Was it helpful?

Solution

This line of code is effectively setting the image to nil on the object.

//set images back to nil for next time AddTarget is opened
self.target.targetImage = nil;

perhaps you should be doing this instead

self.target = nil;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top