我有一个CoreData实体,在不同长度的比赛中有多个性能记录。我想在每个比赛中为每个运动员提供最佳性能,然后将结果放入CoreData Table View。
这是我为实现这一目标而想出的黑客行为。但是,这会干扰我将结果放入TableView的能力,其中比赛距离是节标题:
- (void)setupFetchedResultsController // attaches an NSFetchRequest to this UITableViewController
{
MarksFromMeets* results = nil;
NSMutableArray * bestMarks = [[NSMutableArray alloc] init];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MarksFromMeets"];
// NSLog(@"self.athlete.athleteID = %@",self.athlete.athleteID);
request.predicate = [NSPredicate predicateWithFormat:@"(ANY whoRan.athleteID in %@) AND (eventPR > 0)",
self.athleteIDsForPredicate];
/* Call the records for selected athletes (PLURAL) */
request.sortDescriptors = [NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:@"whoRan.athleteID" ascending:NO],
[NSSortDescriptor sortDescriptorWithKey:@"event" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"sortMark" ascending:YES],
nil];
以下区块中的代码是我为每位运动员提供最佳表现的地方。
NSArray * allMarks = [self.headToHeadManagedObjectContext executeFetchRequest:request error:nil];
MarksFromMeets* tempMark;
for (MarksFromMeets* athletePRs in allMarks) {
if (tempMark == nil) {
tempMark = athletePRs;
} else {
if ([athletePRs.whoRan.athleteID isEqualToString:tempMark.whoRan.athleteID]) {
if ([athletePRs.event isEqualToString:tempMark.event]) {
if (athletePRs.sortMark < tempMark.sortMark) {
tempMark = athletePRs;
}
} else {
[bestMarks addObject:tempMark];
tempMark = athletePRs;
}
} else {
[bestMarks addObject:tempMark];
tempMark = athletePRs;
}
}
}
if (debug == 1) NSLog(@"bestMarks count: %lu \nallMarks count: %lu", (unsigned long)[bestMarks count], [allMarks count]);
[self setResultsArray:bestMarks];
NSArray bestMarks有27个NSManagedObjects,而获取请求返回35个。
下面的代码是我如何使用,并且仍然更喜欢填充我的CoreData TableView。
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.headToHeadManagedObjectContext
sectionNameKeyPath:@"event"
cacheName:nil];
NSError* error = nil;
results = [[self.headToHeadManagedObjectContext executeFetchRequest: request error:&error]objectAtIndex:0];
NSError* requestError = nil;
NSUInteger myCount = [self.headToHeadManagedObjectContext countForFetchRequest:request error:&requestError];
NSLog(@"In %@ and count of results = %lu", NSStringFromClass([self class]),(unsigned long)myCount);
if (!myCount || myCount == 0) {
NSMutableString* titleText = [NSMutableString stringWithFormat:@"No Records Found"];
NSMutableString* messageText = [NSMutableString stringWithFormat:@"There were no records found for the %lu athletes selected. Contact ITrackPerfomance using this list of Athlete ID's: %@", (unsigned long)[self.athleteIDsForPredicate count], self.athleteIDsForPredicate];
NSString* cancelText = @"Okay";
[self displayAlertBoxWithTitle:(NSString*)titleText message:(NSString*) messageText cancelButton:(NSString*) cancelText];
}
}
有没有办法用NSFetchRequest谓词来做到这一点?
或者我可以通过将管理对象放入NSDurray的NSArray来创建部分,其中每个NSDictionary都是不同的种族距离?
感谢您的帮助。如果我完全偏离正确的道路并且有更有效的方法来实现这一点,我也很高兴知道这一点!
答案 0 :(得分:0)
好的,这就是我想出的。希望这有助于其他人: 我根据“类”(在我的情况下为race)将Managed Objects解析为NSMutableArrays。然后我使用将每个NSM数组放入NSMutableDictionary中,其中索引充当键。然后,该字典及其中的数组成为确定节的数量和节中行数的基础。
- (void)setupFetchedResultsController // attaches an NSFetchRequest to this UITableViewController
{
MarksFromMeets* results = nil;
NSMutableArray * bestMarks = [[NSMutableArray alloc] init];
NSMutableDictionary * dictionaryOfMarksByRace = [[NSMutableDictionary alloc] init];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MarksFromMeets"];
// NSLog(@"self.athlete.athleteID = %@",self.athlete.athleteID);
request.predicate = [NSPredicate predicateWithFormat:@"(ANY whoRan.athleteID in %@) AND (eventPR > 0)",
self.athleteIDsForPredicate];
/* Call the records for selected athletes (PLURAL) */
request.sortDescriptors = [NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:@"event" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"whoRan.athleteID" ascending:NO],
[NSSortDescriptor sortDescriptorWithKey:@"sortMark" ascending:YES],
nil];
NSArray * allMarks = [self.headToHeadManagedObjectContext executeFetchRequest:request error:nil];
MarksFromMeets* previousMark;
int i = 0;
int j = 0;
for (MarksFromMeets* athletePRs in allMarks) {
NSArray* sortedMarks;
if (previousMark == nil) {
previousMark = athletePRs;
} else {
if ([athletePRs.event isEqualToString:previousMark.event]) {
if ([athletePRs.whoRan.athleteID isEqualToString:previousMark.whoRan.athleteID]) {
NSLog(@"athletePRs.%@ = previousMark.%@",athletePRs.sortMark,previousMark.sortMark);
if ([athletePRs.sortMark intValue] < [previousMark.sortMark intValue]) {
previousMark = athletePRs;
NSLog(@"Should NEVER happen");
}
} else {
[bestMarks addObject:previousMark];
NSLog(@"Adding %@, %@, %@ to bestMarks for i = %d",previousMark.event, previousMark.markInEvent, previousMark.whoRan.athleteFullName,i);
previousMark = athletePRs;
NSLog(@"tempMark record now %@",previousMark.whoRan.athleteFullName);
if (j == [allMarks count]-1) {
[bestMarks addObject:previousMark]; //Now tempMark is last MarksForMeet object
sortedMarks = [self sortNSMutableArray:bestMarks];
[dictionaryOfMarksByRace setObject:sortedMarks forKey:[NSNumber numberWithInt:i]];
bestMarks = [[NSMutableArray alloc] init];
}
}
} else {
[bestMarks addObject:previousMark];
previousMark = athletePRs;
sortedMarks = [self sortNSMutableArray:bestMarks];
[dictionaryOfMarksByRace setObject:sortedMarks forKey:[NSNumber numberWithInt:i]];
NSLog(@"Adding %@ to bestMarks for i = %d",previousMark.event,i);
bestMarks = [[NSMutableArray alloc] init];
// reallocate bestMarks to ensure values in NSMutableDictionary are unique
i++;
if (j == [allMarks count]-1) {
[bestMarks addObject:previousMark];
sortedMarks = [self sortNSMutableArray:bestMarks];
[dictionaryOfMarksByRace setObject:sortedMarks forKey:[NSNumber numberWithInt:i]];
bestMarks = [[NSMutableArray alloc] init];
// reallocate bestMarks to ensure values in NSMutableDictionary are unique
}
}
}
j++;
}
[self setResultsDictionary:dictionaryOfMarksByRace];
}
过滤数据后不得不去度假。可能有一种更有效的方法,但这种强力方法有效,因为我在此方法中从Core Data中提取相对较少的记录。