我在Objective-C工作,在我的程序中遇到了一致的问题。我有一堆NSTableViews,到目前为止,我总是不得不在我的两个函数中“重新加载”数据:numberOfRowsInTableView和用内容填充它们的那个。
例如,我的“loadData()”函数使用获取请求(使用Core Data)填充在我的.h文件中声明的数组。
我想只需要在我的“awakeFromNib”函数中访问这个loadData()函数,或者只需要更新内容。但是我发现如果我没有在两个必要的NSTableView函数的顶部添加对函数的调用,程序就会崩溃。
这开始引起问题,因为我认为在没有任何变化的情况下从Core Data文件中不断获取是非常多余的。
以下是一些代码:
- (int)numberOfRowsInTableView:(NSTableView *)aTableView {
[self loadData];
if ([aTableView isEqual:(invoicesListTable)])
{
return (int)[fetchedInvoices count];
}}
如果我不包含[self loadData]功能,程序将崩溃。即使我在awakeFromNib函数中有[self loadData],也会发生这种情况。
为什么我的程序“不记住”fetchedInvoices数组的值?它在我的.h文件中声明如下:NSArray *fetchedInvoices;
我的“loadData”函数如下:
- (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
任何帮助都将不胜感激。
答案 0 :(得分:3)
由于您没有使用ARC - 我在您的代码中看到了对-release
的调用 - 您必须确保对象在您需要的时间内保持不变。
特别是,-executeFetchRequest:error:
返回您不拥有的数组。它的寿命是不可预测的。由于您长时间保留它,您需要保留它。如果你保留它,那么你当然也有责任在你不再需要时释放它。
确保正确管理内存(不使用ARC)的最佳方法是将其限制在-init
,-dealloc
以及属性的设置者。因此,您应该使用正确的所有权语义(@synthesize
,fetchedInvoices
或strong
)为retain
实施或copy
设置器,并使用它来设置属性,而不是直接分配实例变量。
因此,举例来说,您可以在课程@interface
中添加以下内容:
@property (copy) NSArray *fetchedInvoices;
然后,在您的@implementation
中,您将拥有:
@synthesize fetchedInvoices;
或者您将使用其声明所需的语义来实现setter。
然后,而不是这一行:
fetchedInvoices = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
你会这样做:
self.fetchedInvoices = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
或等效地:
[self setFetchedInvoices:[managedObjectContext executeFetchRequest:fetchRequest error:&error]];