J'essaye d'analyser un XML que je reçois d'un service Web avec un NSXMLParserDelegate
. La NSObject
Je veux mettre les données dans (je vais juste l'appeler MyObject
) a @property
s qui ne sont pas NSString
s (il y en a des NSDate
s, certains NSNumber
s, et peut-être à un moment donné dans le futur certaines primitives).
Puisque le XML est une grosse chaîne, je reçois des erreurs et des plantages lorsque j'essaie de mettre directement les valeurs du XML dans mes propriétés (j'utilise [myObject setValue:currentElementValue forKey:elementName];
dans mon parser:didEndElement:...
, qui fonctionne normalement bien - quand key
est un NSString
). Je ne m'attendais pas vraiment à ce que cela fonctionne, mais j'ai pensé que cela valait la peine.
La chose la plus simple à faire est simplement le code hardage de tout, donc si j'ai un gerne (@property (non atomique, fort) nsnumber * Âge; ' sur mon objet, quand je trouve le <age>25</age>
une partie de mon XML, je fais MyObject.age = [NSNumber numberWithInt:[currentElementValue intValue]];
. Le problème avec cela est qu'il est très rigide - j'aimerais que ce code soit plus dynamique que cela. Je ne veux pas avoir à savoir quelles sont toutes les propriétés de mon objet à l'avance.
J'ai également essayé de vérifier ce que le class
de la propriété est, puis faire une conversion avant d'entrer une valeur (donc quelque chose comme [myObject setValue:[NSNumber numberWithInt:[currentElementValue intValue] forKey:elementName];
Si la propriété isKindOfClass:[NSNumber class]]
. Le problème avec cela est que c'est la première fois que la propriété est utilisée, donc c'est nil
, et n'a donc pas de classe. Donc, cette approche ne fonctionne pas non plus non plus.
Est-ce que je fais complètement mal? Il semble qu'il devrait être assez typique d'obtenir des données d'un XML et de les mettre en nonNSString
Variables, mais je n'arrive pas à le faire fonctionner.
Si quelqu'un a besoin de voir plus de code pour mieux comprendre comment je suis configuré ou ce que j'ai déjà essayé, faites-le moi savoir.
Edit: J'ai trouvé un exemple rapide de ce que j'essaie de faire. Supposons que j'ai le XML suivant:
<Object>
<ITEM_NUMBER>4</ITEM_NUMBER>
<IS_AWESOME>YES</IS_AWESOME>
<AWESOMENESS>9000.1</AWESOMENESS>
</Object>
que je veux analyser une instance de MyObject
(un NSObject
sous-classe)
@interface MyObject: NSObject
@property (nonatomic, assign) int ITEM_NUMBER;
@property (nonatomic, assign) BOOL IS_AWESOME;
@property (nonatomic, assign) float AWESOMENESS;
@end
Et un deuxième XML
<OtherObject>
<PRICE>4.99</PRICE>
<QUANTITY>5</QUANTITY>
<FOR_RESALE>NO</FOR_RESALE>
</OtherObject>
qui ira dans un cas de OtherObject
(aussi NSObject
sous-classe)
@interface OtherObject: NSObject
@property (nonatomic, assign) int QUANTITY;
@property (nonatomic, assign) BOOL FOR_RESALE;
@property (nonatomic, assign) float PRICE;
@end
Je veux créer un analyseur "modèle" (qui a @property (nonatomic, strong) NSObject *instance;
et alors NSMutableString *currentElementValue
comme un 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 ...
}
...
Ensuite, je sous-classe juste cet analyseur de "modèle" pour chacun de mes différents XML et écrase le init
méthode pour que
self.instance = [[MyObject alloc] init];
ou
self.instance = [[OtherObject alloc] init];
le cas échéant. J'ai beaucoup de services Web que j'appelle que je vais obtenir du XML structuré de la même manière, donc seulement avoir à changer 1 ligne dans les analyseurs pour chacun est quelque chose qui est très souhaitable. Avoir tout le reste du code d'analyse dans une seule classe "modèle" facilitera le maintien, la lecture et le débogage du code.
De toute évidence, le problème que j'ai est isKindOfClass
n'accepte pas int
, float
, ou BOOL
comme entrées. Y a-t-il quelque chose de similaire que je peux utiliser à la place?