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;
}