I'm storing in Core Data
2 date properties, one is expire date and second is "amber" date (the date that is X weeks before expire date). I want to sort results in following way:
Can you help me with that?
UPDATE After more research I've found that I could fetch results unsorted, put it in the array and sort the array and table would use this array as data source - too much to change to have it working in my app. Also there is possibility to use extra parameter which will hold evaluated value based on the list above. The fetch then would require 2 steps:
The latter solution is my best option, so could anyone help me with that part?
EDIT
The state
property is defined as int16_t
@property (nonatomic, assign) int16_t state;
In viewDidLoad
of the view with table I call fallowing before fetching the sorted results:
NSFetchRequest *fetchRequest =
[NSFetchRequest fetchRequestWithEntityName:@"MyTable"];
NSSortDescriptor *sortTitle =
[NSSortDescriptor sortDescriptorWithKey:@"name"
ascending:YES];
[fetchRequest setSortDescriptors:@[sortByTitle]];
NSFetchedResultsController *ctrl = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:[NSManagedObjectContext defaultContext]
sectionNameKeyPath:nil
cacheName:nil];
NSError* fetchError = nil;
if([ctrl performFetch:&fetchError] == NO) {
NSLog(@"Error: perform fetch failed, %@",[fetchError description]);
} else {
//do we have results here?
id <NSFetchedResultsSectionInfo> sectionInfo =
[ctrl.sections objectAtIndex:0];
NSArray * items = [sectionInfo objects];
for (int i=0; i<items.count; i++) {
CourseCD* item = items[i];
NSLog(@"%d - %@",i,item);
[item evaluateState];//category adds this method
}
}
This is the method from category
-(State) evaluateState {
CourseComplianceState pState = StateUnknown;
if (self.expire == nil) {
[self setState:pState];
return pState;
}
NSDate* now = [[NSDate alloc] init];
pState = StateNotExpired;
if ([NSDate isDate:now inRangeFirstDate:self.thresholdDate
lastDate:self.expireDate]) {
//amber
pState = StateWithinThreshold;
} else if ([NSDate isDate:now inRangeFirstDate:self.expireDate
lastDate:[NSDate distantFuture]]){
//expired
pState = StateExpired;
}
//
[self setState:pState];
NSLog(@" - evaluateState -");
return pState;
}
And this is the State struct
enum {
StateUnknown,
StateNotExpired,
StateWithinThreshold,
StateExpired
};
typedef int16_t State;
Then after this call I use the destination call with following sorts and I'm using controller that works with table.
//later I use following sort descriptors
NSSortDescriptor *sortState = [NSSortDescriptor
sortDescriptorWithKey:@"state"
ascending:YES];
NSSortDescriptor *sortExpire = [NSSortDescriptor
sortDescriptorWithKey:@"expire"
ascending:YES];
EDIT
NSSortDescriptor *sortByTitle = [NSSortDescriptor
sortDescriptorWithKey:@"name"
ascending:YES];
NSFetchRequest *fetchRequest = [NSFetchRequest
fetchRequestWithEntityName:@"Course"];
[fetchRequest setSortDescriptors:@[sortState,sortExpire,sortByTitle]];
self.resultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:[NSManagedObjectContext defaultContext]
sectionNameKeyPath:nil
cacheName:nil];
self.resultsController.delegate = self;
NSError* fetchError = nil;
if([self.resultsController performFetch:&fetchError] == NO) {
NSLog(@"Error: perform fetch failed, %@",[fetchError description]);
}
But it only sorts by the expire date and state is ignored or not saved by this first evaluation run.
EDIT 2014/06/10
This is the setter in the NSManagedObject class
//.h
@property (nonatomic, assign) int16_t state;
//.m
@synthesize state=_state;
-(void) setState:(int16_t)state {
_state = state;
NSError* error = nil;
[[NSManagedObjectContext defaultContext] save:&error];
if(error != nil){
NSLog(@"Error in setState, details:%@",[error description]);
}
}
FINAL EDIT - RESOLVED
The resolution was to:
remove @synthesise state = _state;
and -(void) setState:(int16_t)state {}
and leave @dynamic state
. Then in evaluateState
instead of [self setState:pState];
I used self.state=pState;
and now it sorts as required. The question now is why with synthesised property it didnt worked?
The resolution was to: remove @synthesise state = _state;
and -(void) setState:(int16_t)state {}
and leave @dynamic state. Then in evaluateState
instead of [self setState:pState];
I used self.state=pState;
and now it sorts as required.