objectForKey stringValue сбой моего приложения? - PullRequest
2 голосов
/ 01 декабря 2009

У меня есть класс, который я использую для настройки объектов в массиве. В этом классе у меня есть пользовательский "initWithDictionary", где я анализирую словарь JSON. Однако, когда я сталкиваюсь с NSNull, это приводит к сбою моего приложения. Чтобы обойти это, я установил класс, который обрабатывает исключения, поэтому, когда строка равна NSNull, она заменяет ее на @"". или -1 для целых чисел.

Это мой класс NullExtensions:

@interface NSNull (valueExtensions)

-(int)intValue;
-(NSString *)stringValue;

@end

@implementation NSNull (valueExtensions)

-(int)intValue {
    return -1;
}

-(NSString*)stringValue {
    return @"";
}

@end

Однако в моем методе initWithDictionary следующий код приводит к сбою моего приложения:

self.bookTitle = [[parsedDictionary objectForKey:@"book_title"] stringValue];

Он не работает независимо от того, является ли объект в разобранном словаре NSNull или содержит допустимую строку. Только если я сделаю следующее (и строка не будет нулевой):

self.bookTitle = [parsedDictionary objectForKey:@"book_title"];

Является ли stringValue неправильным в этом случае? И если да, то как мне правильно его использовать для настройки правильных NSNull замен?

Thx

Ответы [ 6 ]

5 голосов
/ 01 декабря 2009

Вы действительно действительно не хотите добавлять категорию в NSNull, которая добавляет такие распространенные методы. Это изменит поведение NSNull для всех экземпляров в приложении, в том числе созданных базовыми платформами исключительно для их личного использования.

Если вам нужен класс значений, представляющий понятие «значение не существует, и поэтому вместо этого я собираюсь вернуть эти значения по умолчанию», создайте класс или экземпляр, который представляет именно это.

Что касается причин сбоя, я не могу сказать вам, не увидев фактических подробностей сбоя.

<Ч />

И, да, действительно ЭТО плохо добавлять категорию в класс, который добавляет такой общий метод. Все, что требуется, - это один бит кода в плагине или фреймворке, который делает:

if ([fooMaybeNull respondsToSelector: @selector(intValue)] bar = [fooMaybeNull intValue];

Не слишком притянуто за уши - мне пришлось отлаживать неприятные сбои или неправильное поведение из-за точно такого рода категории волей-неволей.

Если вы собираетесь добавить методы в класс с помощью категорий, добавьте префикс имен ваших методов, чтобы изолировать их от существующей функциональности . Это все еще хрупко, но управляемо так.

4 голосов
/ 01 декабря 2009

Вместо создания категорий на NSNull, для которых вам также нужно будет добавить аналогичную категорию к NSString (именно поэтому она вылетает, потому что реальные строки не отвечают на stringValue) - вместо этого попробуйте создать вспомогательную категорию на NSDictionary подобно "stringForKey", использующему код, опубликованный Джоханом и возвращающий NSString, вероятно, также должно обеспечивать принудительное сопоставление всех других типов с пустыми строками.

3 голосов
/ 01 декабря 2009

Расширения NSNull, которые вы написали, выглядят хорошо для меня, но использование метода, такого как stringValue, может сбивать с толку, поскольку другие классы, такие как NSNumber, используют это.

Лично я думаю, что замена NSNull в этом случае не нужна. Если вы только что сделали быстрый тест, вы можете заменить NSNull там, где вам нужно. например,

id testObject = [parsedDictionary objectForKey:@"book_title"];
self.bookTitle = testObject==[NSNull null] ? @"" : testObject;
3 голосов
/ 01 декабря 2009

Вы запрашиваете NSString для его stringValue. Нет необходимости преобразовывать строку в строку.

Попробуйте это:

if (![[parsedDictionary objectForKey:@"book_title"] isKindOfClass:[NSNull class]]) {
    self.bookTitle = [parsedDictionary objectForKey:@"book_title"];
} else {
    self.bookTitle = @"";
}

Редактировать: Вы не должны использовать категорию на NSNull, которую вы создали. Вам это не нужно, и вы не должны этого хотеть. Если источник для словаря вставляет NSNull экземпляры, продолжайте и используйте мой код выше. Обычно вы ожидаете, что для простого ключа не будет вставлено значение, и в этот момент вы можете просто увидеть, возвращает ли [parsedDictionary objectForKey:@"book_title"] что-либо.

0 голосов
/ 01 декабря 2009

Однако в моем методе initWithDictionary следующий код приводит к сбою моего приложения:

self.bookTitle = [[parsedDictionary objectForKey:@"book_title"] stringValue];

Он не работает независимо от того, является ли объект в разобранном словаре NSNull или содержит допустимую строку.

Это имеет смысл, поскольку stringValue не является допустимым методом для NSString. Он будет работать для NSValue и его подклассов, но не для NSString.

0 голосов
/ 01 декабря 2009

Вы уверены, что словарь возвращает [NSNull null]? По умолчанию словари возвращают nil, а не [NSNull null], если для ключа не найдено значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...