使用带有NSString和NSDate的NSDateFormatter时,NSDate区域设置会导致其他语言环境出现问题

时间:2014-03-12 13:47:22

标签: ios iphone core-data nsdateformatter nsfetchedresultscontroller

我现在有一个正在运行的应用程序,但我遇到了一个很大的障碍。该应用程序的前提是标签栏控制器(TB),它有两个标签,每个标签包含一个表视图。用户点击导航栏中的加号按钮并填写名称和事件文本字段并从日期选择器中选择日期来填充表视图1(TV1)。表视图2是用户已创建的每个唯一事件的图示。如果表1按时间顺序显示每个事务,表2仅显示唯一事件名称,以便您可以按事件查看事务。

我使用Core Data和NSFetchedResultsControllers将所有内容绑定在一起。

这项工作非常顺利,但我希望介绍更新。

如果用户点击表2并看到显示的事件,例如周年纪念,生日和婚礼,然后点击说,生日,他们将看到事件=生日(所选事件场景)的所有交易。我在这里放置了一个新的导航栏按钮(选定的事件),以允许用户添加一个新条目,其中已经从所选事件填充了日期和事件。

我有95%的工作。问题归结为NSLocales和Date Formatters。

我会在这里放一些代码,然后讨论这个问题:

在添加条目中,date和datePicker的NSCalendar为:

    NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    // Will explain the commented out lines    
    //NSLocale *brLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
    //[cal setLocale:brLocale];
    NSDateComponents *components = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
                                          fromDate:self.datePicker.date];
    [components setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
    NSDate *selectedDate = [cal dateFromComponents:components];

在此更新之前,我没有在此代码中使用区域设置(注释掉代码),因为它只使用本地设备并且运行良好。现在我必须添加它以使下一部分工作。

在Selected Event Controller中,prepareForSegue为:

if ([segue.identifier isEqualToString:@"Create New Entry From Event"])
{
    AddEntryViewController *addEntryViewController = (AddEntryViewController *)segue.destinationViewController;
    [addEntryViewController setSelectedEvent:self.occasion.title];

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0] ;
    NSString *sectionTitle = [self tableView:self.selectedOccasionTableView titleForHeaderInSection:indexPath.section];

    NSLog(@"The section header is: %@", sectionTitle);

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"MMMM d, yyyy"];
    NSDate *dateFromString = [[NSDate alloc] init];
    dateFromString = [dateFormatter dateFromString:sectionTitle];
    NSLog(@"The new date is %@", [dateFormatter stringFromDate:dateFromString]);
    [addEntryViewController setSelectedDate:dateFromString];
    [addEntryViewController setIsFromSelectedEvent:YES]; 
}

我从章节标题中获取日期并将其发送到添加条目,其中:

- (void)setSelectedDate:(NSDate *)selectedDate
{
    _selectedDate = selectedDate;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.occasionTextField.text = self.selectedEvent;

    if (self.isFromSelectedEvent)
    {
        NSLog(@"This gets run");
        [self.datePicker setDate:self.selectedDate animated:YES];
    }
}

我遇到的问题是 - 如果将设备区域设置设置为除美国区域设置之外的任何内容(应用程序未在上面注释掉),则应用程序崩溃。当然这是不可取的。

为了让应用程序使用这种格式的日期已经付出了很多努力,我无法改变它,因为很多都取决于节标题中的日期。

我需要一种方法来调整prepareForSegue中的NSDateFormatter代码,以考虑设备使用的任何格式。

下面的代码是将NSDate转换为NSString,因此它在部分标题中是可读的,但这里是问题所在。

-(NSString *)sectionDateFormatter
{
    return [NSDateFormatter localizedStringFromDate:self.dates.dateOfEvent
                                          dateStyle:NSDateFormatterLongStyle
                                          timeStyle:NSDateFormatterNoStyle];
}

如果用户使用美国语言环境,则日期将显示为月份日期,年份。如果用户使用英国语言​​环境,那么它将是日期月份年份。

我需要以某种方式解决这个问题。我要么:

1)将NSDate / NSString的语言环境设置为一种特定格式,而不管语言环境如何,或者 2)操纵代码以支持所有潜在的语言环境。

1号似乎更容易,但我不知道如何实现这一目标。如果你当然使用它,我需要这个应用程序不会崩溃。

如果您使用的是英国语言环境,则会崩溃:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: date'

无论你身在何处,我都需要一种坚持一种格式的方法。例如,我希望将格式设置为" Date Month,Year"无论您是在美国使用美国语言环境,还是在新加坡使用新加坡语区域设置。

在这里,任何正确方向的想法都会受到重视。

1 个答案:

答案 0 :(得分:1)

要根据当前区域设置控制日期格式,请定义格式而不是使用日期/时间样式。例如,如果您使用

[dateFormatter setDateFormat:@"MMMM dd, yyyy"]; 

或您要显示的任何其他格式。您可以使用此日期格式化程序

创建字符串对象
[dateFormatter stringFromDate:self.dates.dateOfEvent];

在此处阅读各种格式字符串:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW1