InitWithString NSDate: возвращает ноль - PullRequest
0 голосов
/ 30 апреля 2011

Я использую Stig Brautaset фреймворк JSON для сериализации некоторых объектов, включая NSDates (которые не поддерживаются напрямую).

Я решил использовать описание NSDate как представление JSONFragment длядата (меня не волнует незначительная потеря точности при этом).

Чтобы расширить структуру JSON Стига Браутасета , чтобы включить NSDates, я определил категорию:

@interface NSDate  (NSDate_JSON) <JSONInitializer>

-(NSString *) JSONFragment;

@end

Чтобы воссоздать NSDate (и другие классы) из JSON, я определил протокол со следующим инициализатором:

@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

Я не уверен, что происходит.Кроме того, компилятор предупреждает меня, что initWithString: метод в initWithJSONRepresentation: не может быть найден.

Кто-нибудь знает, что может происходить?

Полный исходный код для тестового примера доступен здесь .

Ответы [ 3 ]

3 голосов
/ 30 апреля 2011

Вы должны всегда использовать NSDateFormatter при попытке преобразовать строку в дату или наоборот.-initWithString: существует на Mac, но не на iOS.Требуется, чтобы строка была в чрезвычайно точном формате.Использование средства форматирования даты является безусловно лучшим решением.

И, как примечание, ваш код сломался бы, если бы Apple когда-либо решила изменить формат -[NSDate description].

2 голосов
/ 30 апреля 2011

Ваша тестовая программа:

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:].

.так что SBJSON анализирует этот фрагмент и возвращает строку без кавычек, он должен работать.

1 голос
/ 30 апреля 2011

Причина initWithString: не может быть найдена в том, что, если вы не импортируете Foundation и не показывали нас здесь, ваш код не может видеть NSDate.h, поэтому он не знает, что initWithString: существует .

Дейв совершенно прав, полагаясь на description и вместо него NSDateFormatter. Маловероятно, что description изменится, но нет никакой гарантии, что он останется действительным вводом для initWithString:, для которого имеет строгое требование ввода :

Строка, которая задает значение даты и времени в формате международного строкового представления - YYYY-MM-DD HH:MM:SS ±HHMM, где ±HHMM - смещение часового пояса в часах и минутах от GMT (например, «2001-03-24 10:45:32 +0600»).

Необходимо указать все поля строки формата, включая смещение часового пояса, которое должно иметь префикс плюс или минус.

Если ваша строка отличается каким-либо образом (включая, как стало очевидно, наличие в ней кавычек), вы получите nil.

...