使用 NSFetchRequest 按日期和单元格按时区字母顺序对部分进行排序
Posted
技术标签:
【中文标题】使用 NSFetchRequest 按日期和单元格按时区字母顺序对部分进行排序【英文标题】:Using a NSFetchRequest to sort sections by Date and cells Alphabetically With Timezones 【发布时间】:2014-09-04 14:13:58 【问题描述】:我有一个UITableView
,一开始是空白的,但由用户输入一些信息来填充。用户单击UINavigationBar
中的一个按钮,被带到另一个View Controller
并在UITextField
中填写文本并从UIDatePicker
中选择一个日期。当用户按下Save
时,UITableView
将更新为使用NSFetchedResultsController
和Core Data
。
在UITableView
中,日期由section
标题标题表示,而UITextField
文本在实际cells
中表示。
NSFetchRequest 按日期排序,然后按人的字母顺序。
问题
这不是一种常见的情况,但是如果我在纽约时区添加一个人名 A 的条目,然后添加另一个人名 B 的具有相同日期的条目,它将显示 A 然后 B命令。
如果我更改为伦敦时区并添加另一个人名 A 且日期相同的条目,则此新条目现在位于 B 下方。
我明白为什么会发生这种情况,但我不知道该怎么做才能解决它。
代码
这是我的NSFetchReqest
:
- (NSFetchedResultsController *)fetchedResultsController
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
if (_fetchedResultsController != nil)
return _fetchedResultsController;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entity;
if ([self.timelineSearchBar.text length] > 0)
NSPredicate *predName = [NSPredicate predicateWithFormat:@"whoBy.name CONTAINS[c] %@", self.timelineSearchBar.text];
NSPredicate *predOccasion = [NSPredicate predicateWithFormat:@"occasion.title CONTAINS[c] %@", self.timelineSearchBar.text];
NSPredicate *predSubOccasion = [NSPredicate predicateWithFormat:@"subevent.title CONTAINS[c] %@", self.timelineSearchBar.text];
NSPredicate *compPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[predName, predOccasion, predSubOccasion]];
[fetchRequest setPredicate:compPredicate];
// Sorting by date and by name.
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"dates.dateOfEvent" ascending:NO];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"whoBy.name" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
fetchRequest.sortDescriptors = @[sort, sortDescriptor];
fetchRequest.fetchBatchSize = 20;
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"sectionDateFormatter" cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
排序描述符是按日期排序,然后按名称排序,因此发生这种情况是有道理的。
这是我的保存方法:
- (IBAction)save:(id)sender
// Start by obtaining the managedObjectContext.
NSManagedObjectContext *context = [self managedObjectContext];
// Insert a new transaction
Transaction *transaction = [NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:context];
Person *enteredPerson = (Person *)[Person personWithName:self.nameTextField.text inManagedObjectContext:context];
transaction.whoBy = enteredPerson;
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:self.datePicker.date];
NSDate *selectedDate = [cal dateFromComponents:components]; */
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:self.datePicker.date];
NSDate *selectedDate = [cal dateFromComponents:components];
Date *date = (Date *)[Date occasionWithDate:selectedDate inManagedObjectContext:context];
transaction.dates = date;
// Save the ManagedObjectContext
NSError *error = nil;
if (![context save:&error])
// Error
[self dismissViewControllerAnimated:YES completion:nil];
我没有对时区做任何花哨的事情,但如果我将NSDateComponent
、NSCalendar
和/或UIDatePicker
设置为[NSTimeZone localTimeZone]
,我会得到相同的行为。
基本上,我希望先按日期排序,然后按名称排序,但在每个日期内,我只想按名称排序。它都是相同的日期(但只是使用不同的时区创建),因此它将其视为同一时间的较晚时间。我没有利用任何时间。
【问题讨论】:
【参考方案1】:将您的日期保存为同一时区的日期,例如如有必要,将日期转换为 GMT。您可以将时区信息添加到数据模型或根据运行时设置动态更改日期显示。
【讨论】:
谢谢 Mundi - 我明白你的意思,这是有道理的。感谢这里的回答。我以为我错过了一些明显的方式来操纵 NSSortDescriptor 以按预期方式工作。以上是关于使用 NSFetchRequest 按日期和单元格按时区字母顺序对部分进行排序的主要内容,如果未能解决你的问题,请参考以下文章