0

I am currently trying to figure out the best way to access entities in different UIViewControllers. I am currently using the following which seems to have the least live bytes:

View Controller 1 calls this when it wants to present the next view:

fdvc = [[FormDescriptionViewController alloc] initWithNibName:@"FormDescriptionViewController" bundle:nil andDescriptionEntity:mapEntity.desc];

and View Controller 2 (FormDescriptionViewController) is setup using the following:

.h

@property (nonatomic, retain) DescriptionEntity *descriptionEntity;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andDescriptionEntity: (DescriptionEntity *)descE;

.m

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andDescriptionEntity: (DescriptionEntity *)descE
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        self.descriptionEntity = descE;
    }
    return self;
}

When using this method I perform the following in viewDidLoad:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    [self setTitle:@"Form Description"];

    [self.textViewTitle setText:[NSString stringWithString:self.descriptionEntity.map.sName]];

    [self.textViewTitle addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];

    [self.textViewDescription setText:[NSString stringWithString:self.descriptionEntity.sDescription]];

    if (self.descriptionEntity.map.dImage != nil)
    {
        [self.imageView setImage:[UIImage imageWithData:[NSData dataWithData:self.descriptionEntity.map.dImage]]];
    }
    else
        [self.imageView setImage:[UIImage imageNamed:@"wildform.gif"]];

    if ([self.descriptionEntity.map.bDownloaded boolValue] == YES)
        [self.buttonUseForm setTitle:@"Use Map"];
}

These calls are the only calls I have relating to the DescriptionEntity, however when I pop the view controller the memory is never freed. I have performed a heap analysis and it tells me that the DescriptionEntity is the culprit. To confirm this within the dealloc method I tried calling self.descriptionEntity = nil after the [descriptionEntity dealloc]. This frees up the memory when the controller pops, however when I try to push the controlled again I get a bad access so I presume this must now be the only reference to the DescriptionEntity.

I have also tried using an NSFetchedResultsController however this uses over double the live bytes of my current method, and it also fails to free up the memory again when popping the view.

Can anyone explain the best way to access this data in the next view, and does anyone know why my memory wouldn't be freed up again when dealloc is called?

If you need any further information feel free to ask.

EDIT 1 (Where descriptionEntity is declared):

I am currently using NSFetchedResultsController to grab a subsection of my MapEntities and display them within a UITableView. When one of the rows is selected I perform the following to pass the DescriptionEntity into the DescriptionViewController:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    self.viewHasToolbar = YES;

    MapEntity *mapEntity = [_fetchedResultsController objectAtIndexPath:indexPath];

    FormDescriptionViewController *fdvc;

    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        fdvc = [[FormDescriptionViewController alloc] initWithNibName:@"FormDescriptionViewController" bundle:nil andDescriptionEntity:mapEntity.desc];
    } else {
        fdvc = [[FormDescriptionViewController alloc] initWithNibName:@"FormDescriptionViewController_iPad" bundle:nil andDescriptionEntity:mapEntity.desc];
    }

    [self.navigationController pushViewController:fdvc animated:YES];
    [fdvc release];

    [tableView deselectRowAtIndexPath:indexPath animated:NO];
}

The _fetchedResultsController is setup as follows:

@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;

.m

- (NSFetchedResultsController *)fetchedResultsController {

    if (_fetchedResultsController != nil)
        return _fetchedResultsController;

    Singleton *singleton = [Singleton sharedSingleton];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"MapEntity" inManagedObjectContext:[singleton managedObjectContext]];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"sName" ascending:NO];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

    [fetchRequest setFetchBatchSize:8];

    // Finally check the results
    NSError *error;
    NSArray *fetchedObjects = [[singleton managedObjectContext] executeFetchRequest:fetchRequest error:&error];
    for (MapEntity *map in fetchedObjects)
    {
        NSLog(@"Maps present in database: %@", map.sName);
    }


    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[singleton managedObjectContext] sectionNameKeyPath:nil cacheName:@"Root11"];
    self.fetchedResultsController = theFetchedResultsController;
    self.fetchedResultsController.delegate = self;
    [self.fetchedResultsController performFetch:NULL];
    [fetchRequest release];

    return _fetchedResultsController;
}
Elliott D'Alvarez
  • 1,217
  • 16
  • 30
  • The solution probably depends on `mapEntity` in your first code snippet, since that's where you're getting the `descriptionEntity` from. What's the story on that? Does it retain `descriptionEntity`? Does it get deallocated, and if so when? Is it another managed object? – Tom Harrington Jan 28 '13 at 18:08
  • Hi tom, thanks for the response. I have amended my post and added an EDIT 1 section, hopefully this is enough info? – Elliott D'Alvarez Jan 28 '13 at 18:14

0 Answers0