I’m working in Objective-C and coming across a consistent problem in my program. I have a bunch of NSTableViews, and up until this point, I’ve always had to “reload” the data constantly in my two functions : numberOfRowsInTableView and the one that fills them with content.
For example, my “loadData()” function fills an array that’s declared in my .h file with a fetch request (using Core Data).
I would like to only need to access this loadData() function in my “awakeFromNib” function, or whenever things are updated. However I find that the program crashes if I don’t add a call to the function at the top of the two necessary NSTableView functions.
This is starting to cause problems, as I believe it is quite redundant to be constantly fetching from the Core Data file when nothing is changing.
Here is some code:
- (int)numberOfRowsInTableView:(NSTableView *)aTableView {
[self loadData];
if ([aTableView isEqual:(invoicesListTable)])
{
return (int)[fetchedInvoices count];
}}
If I do not include the [self loadData] function, the program crashes. This happens even if I have [self loadData] in the awakeFromNib function.
Why isn’t my program “remembering” the values of my fetchedInvoices array? It is declared in my .h file as follows: NSArray *fetchedInvoices;
My “loadData” function is as follows:
- (void)loadData {
NSError *error = nil;
// fetch all invoices
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Invoice"
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:@"InvoiceNumber" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
fetchedInvoices = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchedInvoices == nil) {
NSLog(@"ERROR");
}
[fetchRequest release];
// end of invoice fetch
Any help would be appreciated.
Since you are not using ARC – I see calls to
-releasein your code – you have to make sure that objects stick around for as long as you want them.In particular, the
-executeFetchRequest:error:returns an array that you don’t own. It has an unpredictable lifetime. Since you are keeping it for an extended period, you need to retain it. If you retain it, then you, of course, have the responsibility to release it when you no longer need it, too.The best way to make sure you get memory management right (short of using ARC) is to confine it to
-init,-dealloc, and the setters of your properties. So, you should implement or@synthesizea setter forfetchedInvoiceswith the proper ownership semantics (strong,retain, orcopy) and use that to set the property, rather than directly assigning the instance variable.So, for example, you might put the following in your class’s
@interface:and then, in your
@implementation, you’d have either:or you would implement the setter with the semantics required by its declaration.
Then, instead of this line:
you would do this:
or, equivalently, this: