【发布时间】:2014-06-09 09:07:11
【问题描述】:
我存储在Core Data 2 个日期属性中,一个是过期日期,第二个是“琥珀”日期(过期日期前 X 周的日期)。我想按以下方式对结果进行排序:
- 琥珀色日期之前的项目 - (绿色)现在
- 琥珀色日期之后但过期日期之前的项目 - (琥珀色)琥珀色
- 过期日期或之后的商品 -(红色)过期
你能帮我解决这个问题吗?
更新 经过更多研究,我发现我可以获取未排序的结果,将其放入数组中并对数组进行排序,并且表将使用该数组作为数据源 - 改变太多以使其在我的应用程序中工作。 也有可能使用额外的参数,它将根据上面的列表保存评估值。然后提取需要 2 个步骤:
- 获取数据并对每个项目运行评估
- 按此获取排序数据 评估属性
后一种解决方案是我最好的选择,所以有人可以帮我解决这个问题吗?
编辑
state 属性定义为int16_t
@property (nonatomic, assign) int16_t state;
在带有表格的视图的viewDidLoad 中,我在获取排序结果之前调用了fallowing:
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
}
}
这是类别中的方法
-(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;
}
这是状态结构
enum {
StateUnknown,
StateNotExpired,
StateWithinThreshold,
StateExpired
};
typedef int16_t State;
然后在此调用之后,我使用具有以下排序的目标调用,并且我正在使用与表一起使用的控制器。
//later I use following sort descriptors
NSSortDescriptor *sortState = [NSSortDescriptor
sortDescriptorWithKey:@"state"
ascending:YES];
NSSortDescriptor *sortExpire = [NSSortDescriptor
sortDescriptorWithKey:@"expire"
ascending:YES];
编辑
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]);
}
但它仅按过期日期排序,第一次评估运行忽略或不保存状态。
编辑 2014/06/10
这是 NSManagedObject 类中的设置器
//.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]);
}
}
最终编辑 - 已解决
决议是:
删除 @synthesise state = _state; 和 -(void) setState:(int16_t)state {} 并离开 @dynamic state。然后在 evaluateState 而不是 [self setState:pState]; 我使用 self.state=pState; 现在它按要求排序。现在的问题是为什么合成属性不起作用?
【问题讨论】:
-
我会将评估作为一个单独的操作运行(在使用
NSFetchRequest获取的项目上)并让 FRC 仅处理 UI,在纸面上您使用更多资源,但它允许您在 FRC 使用批次来补偿为了它。但是是的 - 在同步调用performFetch:之后,您可以访问获取的项目,因此如果这些部分没有按照您预期的方式构建,您应该检查评估代码。 -
评估似乎有效,唯一的问题是它不适用于排序:) 所以状态在单元格中使用并正确显示(如预期的那样)评估状态,但它没有像我一样排序认为它应该被排序:)
setState当从evaluteState调用时调用 save 所以它应该被存储但它不是所以也许这就是问题吗?无论如何,您能否在答案中详细说明您的解决方案并尽可能详细:) 因为对我来说,objective-c 仍然是新的 -
所以问题是您无法读取修改后的属性?那很奇怪。我了解您的代码,因为
evaluateState属于实体类类别,如果是,请分享设置器代码,我想您一定是在使用一些棘手的东西,例如关联对象。 -
我已经更新了问题
-
我明白了,你需要刷新那些属性被这个setter改变的对象,尝试使用
NSManagedObjectContext -refreshObject:mergeChanges:。
标签: ios sorting filter nsfetchrequest nsfetchedresultscontroller