排序/过滤 NSFetchRequest 如何编写将使用当前日期的排序描述符?
Posted
技术标签:
【中文标题】排序/过滤 NSFetchRequest 如何编写将使用当前日期的排序描述符?【英文标题】:Sort/Filter NSFetchRequest how to write sort descriptor taht will use current date? 【发布时间】: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:
。
【参考方案1】:
解决方案是:删除@synthesise state = _state;
和-(void) setState:(int16_t)state
并保留@dynamic 状态。然后在 evaluateState
而不是 [self setState:pState];
我使用 self.state=pState;
现在它按要求排序。
【讨论】:
以上是关于排序/过滤 NSFetchRequest 如何编写将使用当前日期的排序描述符?的主要内容,如果未能解决你的问题,请参考以下文章
核心数据 NSFetchRequest 按类别排序方法返回值