NSDate 的 initWithString: 返回 nil

发布于 2024-11-04 08:08:32 字数 1289 浏览 5 评论 0原文

我正在使用 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: 方法。

有人知道会发生什么吗?

测试用例的完整源代码可在此处获取。

I'm using Stig Brautaset's JSON framework serialize some objects, including NSDates (which are not directly supported).

I decided to use NSDate's description as the JSONFragment representation of a date (I don't care about the minor loss of precision incurred in doing so).

To extend Stig Brautaset's JSON framework to include NSDates, I defined a category:

@interface NSDate  (NSDate_JSON) <JSONInitializer>

-(NSString *) JSONFragment;

@end

To recreate an NSDate (and other classes) from JSON, I defined a protocol with the following initializer:

@protocol JSONInitializer <NSObject>

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

@end

I'm having issues with this initializer. In NSDate's case, it just calls initWithString:, and that's were I get into trouble: it always returns nil. This is the implementation:

#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

I'm not sure what's going on. Besides, the compiler warns me that the initWithString: method in initWithJSONRepresentation: could not be found.

Anybody knows what might be going on?

The full source code for a test case is available here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

离去的眼神 2024-11-11 08:08:33

当尝试将字符串转换为日期时,您应该始终使用NSDateFormatter,反之亦然。 -initWithString: 确实存在于 Mac 上,但不存在于 iOS 上。它要求字符串的格式极其精确。使用日期格式化程序是迄今为止最好的解决方案。

附带说明一下,如果 Apple 决定更改 -[NSDate description] 的格式,您的代码将会损坏。

You should always use an NSDateFormatter when attempting to convert a string into a date or vice versa. -initWithString: does exist on the Mac, but not on iOS. It requires the string to be in an extremely precise format. Using a date formatter is by far the superior solution.

And as a side note, your code would break if Apple ever decided to change the format of -[NSDate description].

神妖 2024-11-11 08:08:33

您的测试程序是:

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 获取该日期的字符串表示形式,然后使用 JSON 表示形式使用 -JSONFragment 获取该字符串。

在 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 解析该片段并返回不带引号的字符串,那么它应该可以工作。

Your test program is:

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];

Your -JSONFragment category method is:

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

What’s happening in this method is that you obtain a string representation of that date using -description, and then a JSON representation of that string using -JSONFragment.

In SBJSON, -JSONFragment returns the representation of a given object as JSON data. The JSON specification requires that strings are quoted. In your program:

NSString *repr = [d1 JSONFragment];

repr contains a string like @"\"2011-04-29 10:20:30 -0600\"". Because of the quotes, that string is not a valid string to be used with -[NSDate initWithString:].

If you change:

NSString *repr = [d1 JSONFragment];

to:

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

so that SBJSON parses that fragment and returns a string without the quotes, it should work.

七婞 2024-11-11 08:08:33

找不到 initWithString: 的原因是,除非您导入 Foundation 并且没有在此处向我们展示,否则您的代码看不到 NSDate.h,因此它不知道 <代码>initWithString:存在。

Dave 关于依赖 description 并使用 NSDateFormatter 的说法非常正确。 description 似乎不太可能改变,但不能保证它将继续是 initWithString: 的有效输入,其中 有严格的输入要求

以国际字符串表示格式指定日期和时间值的字符串 - YYYY-MM-DD HH:MM:SS ±HHMM,其中 ±HHMM 是与 GMT 的时区偏移量(以小时和分钟为单位)(例如“2001-03-24 10:45:32 +0600”)。

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

如果您的字符串有任何不同(包括,正如已经显而易见的那样,其中包含引号),您将得到nil

The reason initWithString: can't be found is that unless you're importing Foundation and didn't show us here, your code can't see NSDate.h, so it doesn't know that initWithString: exists.

Dave's quite right about relying on description and using an NSDateFormatter instead. It doesn't seem likely that description will change, but there's no guarantee that it will continue to be valid input for initWithString: which has a strict input requirement:

A string that specifies a date and time value in the international string representation format — YYYY-MM-DD HH:MM:SS ±HHMM, where ±HHMM is a time zone offset in hours and minutes from GMT (for example, “2001-03-24 10:45:32 +0600”).

You must specify all fields of the format string, including the time zone offset, which must have a plus or minus sign prefix.

If your string differs in any way (including, as has become apparent, having quotes in it), you'll get nil.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文