Sto cercando di analizzare un XML che sto ottenendo da un servizio web con un NSXMLParserDelegate
. Il NSObject
Voglio inserire i dati (li chiamerò e basta MyObject
) ha @property
s che non lo sono NSString
s (ce ne sono alcuni NSDate
S, alcuni NSNumber
s, e forse ad un certo punto in futuro alcuni primitivi).
Dal momento che l'XML è tutto una grande stringa, ricevo errori e crash quando provo a mettere direttamente i valori dall'XML nelle mie proprietà (sto usando [myObject setValue:currentElementValue forKey:elementName];
nel mio parser:didEndElement:...
, che normalmente funziona bene - quando key
è un NSString
). Non mi aspettavo davvero che funzionasse, ma ho pensato che valesse la pena.
La cosa più semplice da fare è solo il code tutto, quindi se ho un'età "@property (non atomica, forte) nsnumber *; sul mio oggetto, quando trovo il <age>25</age>
parte del mio XML, lo faccio MyObject.age = [NSNumber numberWithInt:[currentElementValue intValue]];
. Il problema è che è molto rigido: vorrei che questo codice fosse più dinamico di così. Non voglio sapere quali sono tutte le proprietà del mio oggetto in anticipo.
Ho anche provato a controllare cosa class
della proprietà, quindi sta facendo qualche conversione prima di inserire un valore (quindi qualcosa di simile [myObject setValue:[NSNumber numberWithInt:[currentElementValue intValue] forKey:elementName];
Se la proprietà isKindOfClass:[NSNumber class]]
. Il problema è che questa è la prima volta che viene utilizzata la proprietà, quindi lo è nil
, e quindi non ha una classe. Quindi neanche questo approccio funziona.
Lo sto facendo completamente male? Sembra che dovrebbe essere abbastanza tipico ottenere dati da un XML e metterli in nonNSString
Variabili, ma non riesco a farlo funzionare.
Se qualcuno ha bisogno di vedere più codice per comprendere meglio come sono impostato o cosa ho già provato, fammi sapere.
EDIT: ho escogitato un rapido esempio di ciò che sto cercando di fare. Supponiamo di avere il seguente XML:
<Object>
<ITEM_NUMBER>4</ITEM_NUMBER>
<IS_AWESOME>YES</IS_AWESOME>
<AWESOMENESS>9000.1</AWESOMENESS>
</Object>
che voglio analizzare in un'istanza di MyObject
(un NSObject
sottoclasse)
@interface MyObject: NSObject
@property (nonatomic, assign) int ITEM_NUMBER;
@property (nonatomic, assign) BOOL IS_AWESOME;
@property (nonatomic, assign) float AWESOMENESS;
@end
E un secondo XML
<OtherObject>
<PRICE>4.99</PRICE>
<QUANTITY>5</QUANTITY>
<FOR_RESALE>NO</FOR_RESALE>
</OtherObject>
che andrà in un esempio di OtherObject
(anche NSObject
sottoclasse)
@interface OtherObject: NSObject
@property (nonatomic, assign) int QUANTITY;
@property (nonatomic, assign) BOOL FOR_RESALE;
@property (nonatomic, assign) float PRICE;
@end
Voglio creare un parser "modello" (che ha @property (nonatomic, strong) NSObject *instance;
poi NSMutableString *currentElementValue
come 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 ...
}
...
Quindi, sottoclasse quel parser "modello" per ciascuno dei miei diversi XML e sovrascrivo il init
metodo così
self.instance = [[MyObject alloc] init];
o
self.instance = [[OtherObject alloc] init];
Se appropriato. Ho molti servizi web che chiamo che riceverò XML strutturato in modo simile, quindi dover cambiare solo 1 linea nei parser per ciascuno è qualcosa di molto desiderabile. Avere tutto il resto del codice parser in una singola classe "modello" renderà molto più semplice la manutenzione, la lettura e il debug del codice.
Ovviamente, il problema che sto riscontrando è isKindOfClass
non accetta int
, float
, o BOOL
come input. C'è qualcosa di simile che posso usare invece?