4

次のコードを使用して、NSString の特定の形式から NSDate を作成します。

+ (NSDateFormatter *)serverFormatter
{
    static NSDateFormatter *formatter = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        formatter = [[NSDateFormatter alloc] init];
        [formatter setDateFormat:@"yyyy-MM-dd'T'HHmmssZ"];
    });

    return formatter;
}

+ (NSDate *)dateFromServerDateString:(NSString *)dateString
{
    if (!dateString) {
        return nil;
    }

    NSDateFormatter *formatter = [NSDate serverFormatter];
    NSString *cleaned = [dateString stringByReplacingOccurrencesOfString:@":"
                                                           withString:@""];

    return [formatter dateFromString:cleaned];
}

青月に一度、スタック トレースの表示で EXC_BAD_ACCESS を受け取ります。return [formatter dateFromString:cleaned];クリーニングされた、dateString、およびフォーマッタがすべて正しい値を持っていることを示しています (nil ではなく、「po」はコンソールに正しい値を出力します)。

いくつか読んだ後、コードが NSDateFormatter のスレッド セーフを考慮する必要があることを発見しました。(そして、ここには示されていないコードを適切に調整しました。)しかし、スタック トレースによると、クラッシュが発生したときに NSDateFormatter にアクセスしているスレッドは 1 つだけです。

例外のあるスタック トレースは次のようになります。

#0  0x02d09ad1 in typeinfo name for icu::UObject ()
#1  0x02b8f5ed in icu::TimeZone::getOffset(double, signed char, int&, int&, UErrorCode&) const ()
#2  0x02b95652 in icu::Calendar::computeTime(UErrorCode&) ()
#3  0x02b95552 in icu::Calendar::updateTime(UErrorCode&) ()
#4  0x02b96036 in icu::Calendar::getTimeInMillis(UErrorCode&) const ()
#5  0x02c4244f in icu::DateFormat::parse(icu::UnicodeString const&, icu::ParsePosition&) const ()
#6  0x02cebd05 in udat_parse ()
#7  0x029b7161 in CFDateFormatterGetAbsoluteTimeFromString ()
#8  0x029b6f8e in CFDateFormatterCreateDateFromString ()
#9  0x0214e7e9 in getObjectValue ()
#10 0x0214e701 in -[NSDateFormatter getObjectValue:forString:errorDescription:] ()
#11 0x0214ea3f in -[NSDateFormatter dateFromString:] ()
#12 0x0001a7a4 in +[NSDate(RDUtilities) dateFromServerDateString:]
...

以前にこのようなことに遭遇した人はいますか?デバッグのヒントはありますか?

4

1 に答える 1

0

デバッグのアプローチは次のようになります。

+ (NSDate *)dateFromServerDateString:(NSString *)dateString
{
    if (!dateString) {
        return nil;
    }
    NSLog (@"%@", dateString);
    NSDateFormatter *formatter = [NSDate serverFormatter];
    NSString *cleaned = [dateString stringByReplacingOccurrencesOfString:@":"
                                                           withString:@""];
    NSLog (@"%@", cleaned);  //see if cleaned represents proper string with separators
    NSLog (@"%@", formatter); //not null?

    return [formatter dateFromString:cleaned];
}

形式は、ここで説明されているものに準拠している必要があることに注意してください。詳細については、こちらをお読みください。

アップデート:

NSDateFormatter のようなオブジェクトは、シングルトンに保つのが最適です。そして、それがあなたの元の目的のようです-静的アロケーターと同期された割り当てから。同期ブロックで毎回新しいオブジェクトを作成するように注文すると、おそらくココアがめちゃくちゃになっています。

方法は次のとおりです。

+ (NSDateFormatter *)serverFormatter
{
    static NSDateFormatter *formatter = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
      if (formatter == nil) {
        formatter = [[NSDateFormatter alloc] init];
      }
        [formatter setDateFormat:@"yyyy-MM-dd'T'HHmmssZ"];
    });

    return formatter;
}
于 2013-08-19T06:06:20.020 に答える