NSDate的initWithString:返回nil

时间:2011-04-29 21:52:40

标签: objective-c cocoa protocols nsdate categories

我正在使用Stig Brautaset的JSON框架序列化一些对象,包括NSDates(不直接支持)。

我决定使用NSDate的描述作为日期的JSONFragment表示(我不关心这样做会导致精确度的轻微损失)。

为了扩展Stig Brautaset的JSON框架以包含NSDates,我定义了一个类别:

@interface NSDate  (NSDate_JSON) <JSONInitializer>

-(NSString *) JSONFragment;

@end

要从JSON重新创建NSDate(和其他类),我使用以下初始化程序定义了一个协议:

@protocol JSONInitializer <NSObject>

-(id) initWithJSONRepresentation: (NSString *) aJSONRepresentation;

@end

我遇到了这个初始化程序的问题。在NSDate的情况下,它只调用initWithString:,这就是我遇到麻烦:它总是返回nil。这是实施:

#import "NSDate+JSON.h"


@implementation NSDate (NSDate_JSON)

-(NSString *) JSONFragment{
    NSString *strRepr = [self description];
    return [strRepr JSONFragment];
}

-(id) initWithJSONRepresentation:(NSString *)aJSONRepresentation{


    return [self initWithString: aJSONRepresentation]; //returns nil!
}
@end

我不确定发生了什么。此外,编译器警告我无法找到initWithJSONRepresentation:中的initWithString:方法。

有人知道可能会发生什么吗?

测试用例的完整源代码可用here

3 个答案:

答案 0 :(得分:3)

在尝试将字符串转换为日期时,总是使用NSDateFormatter,反之亦然。 -initWithString:确实存在于Mac上,但不存在于iOS上。它要求字符串格式非常精确。使用日期格式化程序是目前最好的解决方案。

作为旁注,如果Apple决定更改-[NSDate description]的格式,您的代码就会中断。

答案 1 :(得分:2)

您的测试程序是:

NSDate *d1 = [[[NSDate alloc] init] autorelease];
NSString *repr = [d1 JSONFragment];

NSDate *dd = [[[NSDate alloc] initWithString:[d1 description]] autorelease ];
NSDate *d2 = [[[NSDate alloc] initWithJSONRepresentation:repr] autorelease];

您的-JSONFragment类别方法是:

-(NSString *) JSONFragment{
    NSString *strRepr = [self description];
    return [strRepr JSONFragment];
}

此方法中发生的情况是您使用-description获取该日期的字符串表示形式,然后使用-JSONFragment获取该字符串的JSON表示。

在SBJSON中,-JSONFragment将给定对象的表示形式返回为JSON数据。 JSON规范要求引用字符串。在你的计划中:

NSString *repr = [d1 JSONFragment];

repr包含@"\"2011-04-29 10:20:30 -0600\""之类的字符串。由于引号,该字符串不是与-[NSDate initWithString:]一起使用的有效字符串。

如果你改变:

NSString *repr = [d1 JSONFragment];

为:

NSString *repr = [[d1 JSONFragment] JSONFragmentValue];

以便SBJSON解析该片段并返回不带引号的字符串,它应该可以工作。

答案 2 :(得分:1)

找不到initWithString:的原因是除非您导入Foundation并且没有在此处显示,否则您的代码无法看到NSDate.h,因此它不知道{{1} 1}}存在。

Dave完全依赖initWithString:并使用description代替。 NSDateFormatter似乎不太可能会发生变化,但无法保证它会继续作为description initWithString:的有效输入has a strict input requirement

  

以国际字符串表示格式指定日期和时间值的字符串 - YYYY-MM-DD HH:MM:SS ±HHMM,其中±HHMM是GMT小时和分钟的时区偏移量(例如,“{{1 }}”)。

     

您必须指定格式字符串的所有字段,包括时区偏移量,该字段必须具有加号或减号前缀。

如果你的字符串以任何方式有所不同(包括显而易见的,在其中加上引号),你将获得2001-03-24 10:45:32 +0600