我使用以下代码从 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];
}

每隔一次,我都会在 return [formatter dateFromString:cleaned]; 上收到 EXC_BAD_ACCESS 查看堆栈跟踪显示,cleaned、dateString 和 formatter 都有正确的值(不是 nil 和 'po' 在控制台中打印正确的值)。

在读了一些书之后,我确实发现我的代码需要考虑 NSDateFormatter 上的线程安全性。 (我已经适本地调整了我的代码,这里没有显示。)但是,根据堆栈跟踪,当崩溃发生时,只有一个线程正在访问我的 NSDateFormatter。

具有异常的堆栈跟踪如下所示。
#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:]
...

有没有人遇到过这样的事情并且有任何调试技巧?

最佳答案

调试方法是这样的:

+ (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];
}

请注意,您的格式必须符合 described here
如需进一步引用,请阅读 this

更新:

像 NSDateFormatter 这样的对象最好保持单例。这就是您最初的目标似乎是 - 从您的静态分配器和同步分配。当您每次使用同步块(synchronized block)命令它创建新对象时,可能 cocoa 正在搞砸事情。

这是你如何做到的:
+ (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;
}

关于objective-c - dateFromString : crash Objective C,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18307090/

10-12 14:26