我有一个简单的双标签表视图控制器。用户按下加号按钮并以模态方式进入另一个视图控制器,以将文本添加到文本字段中,并从UIDatePicker中选择日期。
除了Core Data和我的约会的重复问题外,一切都运行良好。
在应用程序中,第一个表视图显示基于添加到文本字段的条目的时间,但我已经添加了一些代码来检查在创建之前该时机尚不存在。这意味着如果您将“婚礼”作为一个场合并保存,如果您输入另一个以“婚礼”作为场合的条目,而不是在带有婚礼的表格视图中创建两个单元格,它只创建一个,当您单击时在它上面,它是另一个视图控制器显示婚礼的所有条目。
这很好用。
但是,当谈到UIDatePicker并选择日期时,正在创建重复的项目。
模型是:
交易实体 场合实体 日期实体
交易实体与场合和日期实体有关系。
让我们看看一些代码:
模态视图控制器中的save方法:
- (IBAction)save:(id)sender
{
NSManagedObjectContext *context = [self managedObjectContext];
Transaction *transaction = [NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:context];
Occasion *enteredOccasion = (Occasion *)[Occasion occasionWithTitle:self.occasionTextField.text inManagedObjectContext:context];
transaction.occasion = enteredOccasion;
// Code to save the date as well - shown below
}
这是调用执行NSFetchRequest检查的occasionWithTitle方法:
+ (Occasion *)occasionWithTitle:(NSString *)title inManagedObjectContext:(NSManagedObjectContext *)context
{
Occasion *occasion = nil;
// Creating a fetch request to check whether the occasion already exists
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Occasion"];
request.predicate = [NSPredicate predicateWithFormat:@"title = %@", title];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *occasions = [context executeFetchRequest:request error:&error];
if (!occasions)
{
// Handle Error
}
else if (![occasions count])
{
// If the occasions count is 0 then let's create it
occasion = [NSEntityDescription insertNewObjectForEntityForName:@"Occasion" inManagedObjectContext:context];
occasion.title = title;
}
else
{
// If the object exists, just return the last object .
occasion = [occasions lastObject];
}
return occasion;
}
日期选择器的代码也在save方法中:
Date *date = (Date *)[Date occasionWithDate:self.datePicker.date inManagedObjectContext:context];
transaction.dates = date;
哪个电话:
+ (Date *)occasionWithDate:(NSDate *)enteredDate inManagedObjectContext:(NSManagedObjectContext *)context
{
Date *date = nil;
// Creating a fetch request to check whether the date already exists
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Date"];
request.predicate = [NSPredicate predicateWithFormat:@"dateOfEvent = %@", enteredDate];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"dateOfEvent" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *dates = [context executeFetchRequest:request error:&error];
if (!dates)
{
// Handle Error
}
else if (![dates count])
{
// If the dates count is 0 then let's create it
date = [NSEntityDescription insertNewObjectForEntityForName:@"Date" inManagedObjectContext:context];
date.dateOfEvent = enteredDate;
}
else
{
// If the object exists, just return the last object .
date = [dates lastObject];
}
return date;
}
对我来说,代码看起来是一样的,但当然一个是传递NSString,一个是从UIDatePicker传递一个选定的NSDate。
结果是当涉及到第二个选项卡表视图(对于日期)时,如果我创建一个2013年12月2日的新事务作为日期,然后在2013年12月2日创建另一个条目,它将创建两个单独的单元格同一日期的表格视图,当然这是不对的。
非常感谢任何关于这个令人抓狂的问题的帮助!
编辑:在相关的说明中,我正在从DatePicker中选择日期并将其显示为具有特定格式的TableView的节标题。我正在使用此代码执行此操作:
-(NSString *)sectionDateFormatter
{
return [NSDateFormatter localizedStringFromDate:self.dates.dateOfEvent
dateStyle:NSDateFormatterLongStyle
timeStyle:NSDateFormatterNoStyle];
}
在sectionNameKeyPath中调用它。
答案 0 :(得分:2)
好的,我提供了一个不同的答案,因为你要求回应@Tom是否应该使用字符串来使其工作。答案显然是否定的。
我在Java和Objective-C中完成了很多日期编程。 Java的日期内容(Date / Calendar)是如此蹩脚和不足,首先是另一个团队出现(Joda-Time),现在它正在8中完全重做(JSR 310)。在Java中,曾经有过很简单的方法来构建带有日期等的东西,但显然,所有代码都是在日历的范围之外完成的,因此当语言爆炸时,很快就会发现它很乱并没有工作和大量的弃用导致了。
但是,在Cocoa中,您可以使用日期组件来执行所有这些操作。因此,您可以使用一个日期,然后从中提取您感兴趣的组件,并使用这些组件构建另一个日期。这是编写您不感兴趣的值的正确方法(例如,分钟,秒,毫秒)。
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:6];
[components setMonth:5];
[components setYear:2004];
NSInteger weekday = [components weekday];
即使你打算做一个小日期编程,也可以考虑观看WWDC 2013会议。令人惊讶的是,这不是最好的会议之一,但确实涵盖了一些麻烦的事情。
但是Date and Time Programming Guide的日期必须阅读,而且非常出色。
答案 1 :(得分:1)
这些日期并不完全相同,它们只是在同一天。 UIDatePicker
为您提供完整的NSDate
,其中包含一天中的时间。加载选择器时,时间似乎是固定的,但如果多次加载相同的视图,则会得到不同的时间。例如,在使用Apple的 UICatalog 演示时,我在选择12月3日时会得到2013-12-03 17:20:11 +0000
。如果我通过导航控制器退出然后重新加载相同的视图,我会得到{{1 }}。这些日期与通常使用的术语相同,但它们不同2013-12-03 17:20:22 +0000
。即使它们都在12月3日,它们也不会在谓词中匹配。
如果您只对日期感兴趣,而不是对一天中的时间感兴趣,则需要将选择器中的NSDate
转换为仅具有日期的内容,具有已知的固定时间值或没有时间值。几种可能性:
NSDate
使用仅包含年,月和日的日期格式获取日期字符串。NSDateFormatter
获取从选择器获得的NSCalendar
的年,月和日组件。然后,只需将这些值存储在模型中,或者将这些值转换回NSDate
,其中包含固定的已知值(一天中的时间)(可能会将它们全部归零)。获取值时,第二个会更快(因为您将对数值进行过滤)。第一个可能更容易编写,但对字符串值的过滤会更慢。
如果使用日期组件方法(推荐),请使用从选择器获取的日期执行此类操作:
NSDate
然后将这三个值保存在数据模型中,而不是NSDateComponents *components = [[NSCalendar currentCalendar]
components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:date];
NSInteger year = components.year;
NSInteger month = components.month;
NSInteger day = components.day;
。或者将它们组合成一个整数值并保存:
NSDate
这将为您提供2013年12月2日的整数值NSInteger dateIndex = year * 10000 + month * 100 + day;
。
无论您使用哪种方法,在提取时都要做同样的事情。