2011-04-29 63 views
0

我使用Stig Brautaset的JSON序列化框架的一些對象,包括NSDates(不直接支持)。的NSDate的initWithString:將返回零

我決定使用的NSDate的描述爲日期的JSONFragment表示(我不關心這樣做所產生的精密微小的損失)。

爲了延長Stig Brautaset的JSON框架包括NSDates,我中定義的類別:

@interface NSDate (NSDate_JSON) <JSONInitializer> 

-(NSString *) JSONFragment; 

@end 

要重新創建從JSON一個NSDate(和其它類),I定義的協議具有以下初始化:

@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

+0

'aJSONRepresentation'看起來像什麼? – 2011-04-29 21:57:09

+0

這與NSDate的說明完全一樣 – cfischer 2011-04-29 23:41:04

+2

實際上並非如此。 – 2011-04-29 23:43:47

回答

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獲得該日期的字符串表示,然後該字符串的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分析該片段,並返回不帶引號的字符串,它應該工作。

+0

+1:儘管如此,Dave仍然可能依靠「description」的輸出結果。 – 2011-04-30 00:00:07

+0

@Josh我不確定。 ' - [NSDate description]'和' - [NSDate initWithString:]'的文檔對於字符串表示非常具體。 – 2011-04-30 00:03:19

+0

的確如此,我會向你鞠躬致敬,但如果我不得不猜測,鑑於沒有文檔說明「'description是'initWithString'的有效輸入」,我想說Apple會更願意改變記錄方法的行爲而不是創建對象的方法。或者,我不知道,「描述」是否應該用於其他方面? – 2011-04-30 00:09:19

3

您應該始終嘗試將字符串轉換爲日期時使用NSDateFormatter,反之亦然。在Mac上確實存在-initWithString:,但在iOS上不存在。它要求字符串的格式非常精確。使用日期格式化程序是迄今爲止最優秀的解決方案。

而作爲一個側面說明,如果蘋果曾決定改變的-[NSDate description]格式的代碼將打破。

+0

如果該方法在iOS上不存在,並且我在使用iOS,那麼該應用程序不應該崩潰嗎? – cfischer 2011-04-30 00:02:22

+0

它可能在那裏,只是不作爲API,你不應該依賴無證方法。 'NSDateFormatter'仍然是正確的答案。 – 2011-04-30 00:33:50

1

找不到原因initWithString:是因爲除非您導入Foundation並沒有在此處顯示我們,否則您的代碼無法看到NSDate.h,因此它不知道initWithString:存在。

Dave的非常正確約依託description和使用NSDateFormatter來代替。這似乎並不可能,description會有所改變,但也不能保證它會繼續有效輸入initWithString:其中has a strict input requirement

,指定在國際字符串表示格式的日期和時間值的字符串 - YYYY-MM-DD HH:MM:SS ±HHMM,其中±HHMM是GMT(小時和分鐘)的時區偏移量(例如,「2001-03-24 10:45:32 +0600」)。

您必須指定格式字符串的所有領域,包括時區偏移量,其中必須有一個加號或減號前綴。

如果您的字符串在任何方面有所不同(包括顯而易見的引號),您將獲得nil