Как проверить, является ли объект фундаментальным объектом в какао? - PullRequest
0 голосов
/ 13 декабря 2011

Есть ли способ узнать, является ли произвольный объект в Какао объектом Foundation? Я говорю о NSString, NSArray, NSDictionary и т. Д.

Позвольте мне остановиться подробнее ...

Базовые объекты (AFAIK) имеют некоторые общие характеристики: все они реализуют протокол NSCoding, все они могут входить в PList и т. Д.

Так, например, если я хочу заархивировать граф объектов на диск, было бы полезно убедиться, что любые объекты, которые я добавляю в граф объектов, являются либо объектами Foundation, либо моими пользовательскими объектами, на которых я реализовал NSCoding, и это кажется глупым делать:

if ([myObject isKindOfClass:[NSString class]] || 
    [myObject isKindOfClass:[NSNumber class]] || 
    [myObject isKindOfClass:[NSArray class]] || 
    [myObject isKindOfClass:[NSDictionary class]] || 
    [myObject isKindOfClass:[NSSet class]] || 
    ...) {
    //add myObject to object graph
}

Это простой, но, может быть, бесполезный пример, проблема в том, что я написал код, который преобразует словарь в строку параметров URL, используя строку формата со спецификатором %@, но я этого не делаю Я не хочу, чтобы туда входили произвольные объекты, потому что я не хочу, чтобы в параметрах URL были адреса памяти:

//convert dictionary into url params string
[postDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
    if ([key isKindOfClass:[NSString class]] && ([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSNumber class]])) {
        [tempPost appendFormat:@"%@=%@&", key, obj];
    }
    else {
        *stop = TRUE;
    }
}];
NSString *post;
if ([tempPost length] > 0) {
    post = [tempPost substringToIndex:[tempPost length] - 1];
}

Ответы [ 4 ]

1 голос
/ 14 декабря 2011

Базовые объекты (AFAIK) имеют некоторые общие характеристики: все они реализуют протокол NSCoding, все они могут входить в PList и т. Д.

Ни то, ни другое не является правдой. Только некоторые классы соответствуют NSCoding, не все из которых находятся в Foundation, и только несколько избранных классов являются классами списка свойств.

Вы, конечно, можете сгенерировать plist из объекта, используя один из архиваторов Apple, но тогда объект должен соответствовать NSCoding - см. Выше.

Так, например, если бы я хотел заархивировать граф объектов на диск, было бы полезно убедиться, что любые объекты, которые я добавляю в граф объектов, являются либо объектами Foundation, либо моими пользовательскими объектами, в которых я реализовал NSCoding на…

Вы можете проверить, соответствует ли объект NSCoding с помощью [someObject conformsToProtocol:@protocol(NSCoding)].

Если вам нужно проверить, является ли объект объектом списка свойств, вы должны будете это сделать, протестировав членство в классе, как вы показали в своем вопросе. Такой тест будет включать объекты базового списка свойств Core Foundation, и это правильно: объекты списка свойств CF в списке свойств так же действительны, как и их аналоги Foundation, в основном потому, что объекты списка свойств CF и Cocoa являются взаимозаменяемыми (из-за бесплатный телефонный мост).

Полный список допустимых классов списка свойств содержится в Руководстве по программированию списка свойств и Темы программирования списка свойств для Core Foundation . Конечно, имена классов различны (CFString и NSString), но из-за бесплатного моста они взаимозаменяемы.

Для всех намерений и целей NSString является CFString и наоборот, и то же самое для любой другой пары классов с бесплатными мостовыми соединениями. Бесполезно думать о «NSStrings vs. CFStrings»; вместо этого помните, что это одно и то же , и относитесь к ним как к такому.

Проблема в том, что я написал в коде, который преобразует словарь в строку параметров URL, используя строку формата со спецификатором% @, но я не хочу, чтобы туда входили произвольные объекты потому что я не хочу адреса памяти в моих параметрах URL ...

Это допустимый случай для тестирования членства в классе.

//convert dictionary into url params string
    if ([key isKindOfClass:[NSString class]] && ([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSNumber class]])) {
        [tempPost appendFormat:@"%@=%@&", key, obj];
    }

Таким образом, вы найдете & в конце вашего URL.

Ранее я описал спецификацию для объекта, который форматирует строки URL-запроса . Вы можете включить свои тесты членства в классе в свою реализацию этого объекта.

1 голос
/ 13 декабря 2011

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

if ([someObj.class.description hasPrefix:@"NS"]) {
  NSLog(@"Well, it's an NSSomething object...");
}
1 голос
/ 13 декабря 2011

Вы всегда можете попросить его класс.
Но вы не должны основывать свой код на этом, чтобы принять логическое решение a path to the dark side, that is...
Но если серьезно, Apple выставляет NSString как cluster class, что означает, что под капотом много разных классов, и любой из них может быть возвращен вам, и нет никаких гарантий, что в будущем они будут то же самое, имя может измениться и т. д.
Даже если я сомневаюсь, что старый класс, такой как NSString, изменил бы свою основную структуру, я не исключил бы такую ​​возможность и не сделал бы ставку на нее.

1 голос
/ 13 декабря 2011

Я не совсем уверен, что вы имеете в виду здесь.Вы спрашиваете, какие классы бесплатные по мосту ?

...