Вопрос

Я пытаюсь проанализировать XML, который я получаю от веб -сервиса с NSXMLParserDelegate. Анкет А NSObject Я хочу поместить данные (я просто назову это MyObject) имеет @propertyS, которые не NSStringS (есть некоторые NSDateS, некоторые NSNumberS, и, возможно, в какой -то момент в будущем некоторые примитивы).

Поскольку XML - это большая строка, я получаю ошибки и сбои, когда я пытаюсь просто прямо положить значения из XML в свои свойства (я использую [myObject setValue:currentElementValue forKey:elementName]; в моем parser:didEndElement:..., что обычно работает нормально - когда key это NSString) Я действительно не ожидал, что это сработает, но я подумал, что это стоит попробовать.

Самое простое, что нужно сделать, это просто хард -код всего этого, поэтому, если у меня есть «@property (неатомный, сильный) nsnumber *ровь»; На моем объекте, когда я нахожу <age>25</age> часть моего XML, я делаю MyObject.age = [NSNumber numberWithInt:[currentElementValue intValue]];. Анкет Проблема в том, что она очень жесткая - я бы хотел, чтобы этот код был более динамичным, чем этот. Я не хочу знать, какие свойства моего объекта заранее.

Я также пытался проверить, что class Собственности есть, а затем провести некоторое преобразование, прежде чем ввести ценность (так что что -то вроде [myObject setValue:[NSNumber numberWithInt:[currentElementValue intValue] forKey:elementName]; Если собственность isKindOfClass:[NSNumber class]]. Анкет Проблема в том, что это первый раз, когда свойство используется, так что оно nil, и поэтому нет класса. Так что этот подход тоже не работает.

Я делаю это совершенно неправильно? Кажется, что это должно быть довольно типичным, чтобы получить данные из XML и поместить их в неNSString переменные, но я не могу заставить его работать.

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


РЕДАКТИРОВАТЬ: Я придумал быстрый пример того, что я пытаюсь сделать. Предположим, у меня есть следующий XML:

<Object>
    <ITEM_NUMBER>4</ITEM_NUMBER>
    <IS_AWESOME>YES</IS_AWESOME>
    <AWESOMENESS>9000.1</AWESOMENESS>
</Object>

что я хочу разобраться в экземпляре MyObject ( NSObject подкласс)

@interface MyObject: NSObject

@property (nonatomic, assign) int ITEM_NUMBER;
@property (nonatomic, assign) BOOL IS_AWESOME;
@property (nonatomic, assign) float AWESOMENESS;

@end

И второй XML

<OtherObject>
    <PRICE>4.99</PRICE>
    <QUANTITY>5</QUANTITY>
    <FOR_RESALE>NO</FOR_RESALE>
</OtherObject>

это пойдет в экземпляр OtherObject (также NSObject подкласс)

@interface OtherObject: NSObject

@property (nonatomic, assign) int QUANTITY;
@property (nonatomic, assign) BOOL FOR_RESALE;
@property (nonatomic, assign) float PRICE;

@end

Я хочу создать анализатор «шаблона» (который @property (nonatomic, strong) NSObject *instance; а потом NSMutableString *currentElementValue как ivar)

...
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    [currentElementValue setString:string];
}

- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([[self.instance valueForKey:elementName] isKindOfClass:int])
    {
        [self.instance setValue:[currentElementValue intValue] forKey:elementName];
    }
    else if ([[self.instance valueForKey:elementName] isKindOfClass:float])
    {
        [self.instance setValue:[currentElementValue floatValue] forKey:elementName];
    }
    else if ([[self.instance valueForKey:elementName] isKindOfClass:BOOL])
    {
        [self.instance setValue:[currentElementValue boolValue] forKey:elementName];
    }
    else if ...
}
...

Затем я просто подкласс, этот «шаблон» анализатор для каждого из моих разных XML и перезаписываю init метод, чтобы

self.instance = [[MyObject alloc] init];

или же

self.instance = [[OtherObject alloc] init];

в зависимости от необходимости. У меня есть много веб -сервисов, которые я звоню, что я буду получать аналогично структурированный XML, поэтому необходимость менять только 1 линию в анализаторах для каждого - это то, что очень желательно. Наличие всего остального кода анализатора в одном классе «шаблона» будет намного проще поддерживать, читать и отлаживать код.

Очевидно, что проблема, с которой у меня есть isKindOfClass не принимает int, float, или же BOOL как входные данные. Есть ли что -то подобное, что я могу использовать вместо этого?

Это было полезно?

Решение

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

Objective-C позволяет Свойства класса запросов во время выполнения, Таким образом, интроспекция типа свойства и использование соответствующей Trnsformation - это один из способов.

Вы можете прочитать больше о времени выполнения в блоге Майка Эша или посмотреть Цель C Интроспекция/отражение.

Однако, Эта конкретная проблема столкнулась многие другие люди, так что есть довольно много решений: как сказано в Библиотека служб обслуживания iOS RESTKIT - один хороший пример такой библиотеки; MagicRecord - еще один.

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

Другие советы

Конечно, я мог бы просто переопределить init метод MyObject чтобы выделить все мои свойства на пустые значения, которые должны решить nil Проблема, на которую я ссылался в своем OP, но это просто кажется действительно взломанным. Это может быть единственный вариант, хотя.


РЕДАКТИРОВАТЬ: Этот подход полностью разваливается с примером в редактировании в OP. KVC повернет intс, floatпесок BOOLS все до NSNumberS, без какого -либо способа узнать, что они изначально где. Что означает, что я не смогу позвонить [currentElementValue intValue], [currentElementValue floatValue], или же [currentElementValue boolValue] в зависимости от необходимости.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top