我正在尝试为我的 Cocoa NSTableView 实现一个控制器,该控制器填充了 SQLite 数据库文件的数据。控制器实现了 NSTableViewDataSource 协议和方法
-(NSInteger)numberOfRowsInTableView:(NSTableView*)tableView {
}
和
-(id)tableView:(NSTableView*)tableView setObjectValue:(id)object
forTableColumn:(NSTableColumn*)tableColumn
row:(NSInteger*)row {
}
这显然经常被称为安静(例如,如果我滚动表格)。为了向这两种方法提供最新数据,每次调用其中一种方法时,我都会执行 NSFetchRequest。
实际问题与我的 IBAction 有关,它在我的表中添加了一个新条目。在这个方法的最后,我在表视图上调用 reloadData 方法,如果我是正确的,它至少调用这两个协议方法一次,然后导致表中未排序的数据。我发现每个 NSFetchRequest 都会返回这个未排序的数据,直到我保存 managedObjectContext。但这不是一个选项(甚至不可能),因为有一个必填字段,需要先在表格中填写。
所以这是我的两个问题:
1) 为什么我在 insertNewObjectForEntityForName 调用之后的第一个 fetch 请求(以及在我保存之前的所有进一步请求)会导致未排序的数据?
2)如何在不保存的情况下避免这种行为(因为我不能没有输入的必填字段)?
由于我对整个 Cocoa 和 CoreData 都是新手,所以我将发布我的完整代码,让您清楚地了解我正在尝试做什么。欢迎任何意见。
问候,
理查德
#import "EventTabController.h"
#import "CoreData.h"
#import "Season.h"
@implementation EventTabController
-(id) init {
if(self = [super init]) {
managedObjContext = [[CoreData getInstance] managedObjContext];
}
return self;
}
/**
* Part of the NSTableViewDataSource protocol. This method must return the number of
* elements that are currently to be shown in the table.
*/
-(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
NSError *err;
NSInteger numOfRows = [managedObjContext countForFetchRequest:[self createSeasonFetchRequest] error:&err];
NSLog(@"[%@] %lu objects in table", [self class], (long)numOfRows);
return numOfRows;
}
/**
* Part of the NSTableViewDataSource protocol. This method must return the object for a specific cell,
* The cell is identified by a row number and a NSTableColumn object.
*/
-(id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSError * err;
NSArray* result = [managedObjContext executeFetchRequest:[self createSeasonFetchRequest] error:&err];
Season *season = [result objectAtIndex:row];
NSObject* obj = [season valueForKey:[tableColumn identifier]];
NSLog(@"[%@] Index: %lu - %@", [self class], (long)row, obj);
return obj;
}
/**
* Part of the NSTableViewDataSource protocol. This method sets the value for an entity, that was entered in the table.
* The value to insert is identified by a row number and a NSTableColumn object.
*/
- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSError * err;
NSArray* result = [managedObjContext executeFetchRequest:[self createSeasonFetchRequest] error:&err];
Season *season = [result objectAtIndex:row];
[season setValue:object forKey:[tableColumn identifier]];
}
/**
* Creates a fetch request for the Season entity. The request does not include any subentities.
*/
-(NSFetchRequest*) createSeasonFetchRequest {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Season" inManagedObjectContext:managedObjContext]];
[fetchRequest setIncludesSubentities:NO];
return fetchRequest;
}
/**
* Called when the 'Add Season' button is pressed in the gui. It creates a new (empty) Season object
* within the managedObjectConext and forces the season table to refresh;
*/
- (IBAction)addSeason:(id)sender {
NSLog(@"[%@] 'Add Season' button has been pressed...", [self class]);
[NSEntityDescription insertNewObjectForEntityForName:@"Season" inManagedObjectContext:managedObjContext];
[seasonTable reloadData];
}
@end