質問

私はウェブサービスから得ているXMLを解析しようとしています NSXMLParserDelegate. 。 NSObject データを入れたいです(私はそれを呼ぶだけです MyObject) もっている @propertyそうではないs NSStringS(いくつかあります NSDateS、いくつか NSNumberS、そしておそらく将来のある時点でいくつかのプリミティブ)。

XMLはすべて大きな文字列であるため、XMLから値を自分のプロパティに直接入れようとすると、エラーとクラッシュが発生します(使用しています [myObject setValue:currentElementValue forKey:elementName]; 私の中で parser:didEndElement:..., 、通常は正常に動作します - いつ key aです NSString)。私はこれがうまくいくとは本当に思っていませんでしたが、それはショットの価値があると思いました。

最も簡単なことは、すべてのハードコードだけです。したがって、「@property(非原子、強い)nsnumber *age;」がある場合、 '私のオブジェクトで、私が見つけたとき <age>25</age> 私のXMLの一部、私はします MyObject.age = [NSNumber numberWithInt:[currentElementValue intValue]];. 。これの問題は、それが非常に厳格であることです - 私はこのコードをそれよりもダイナミックにしたいです。私のオブジェクトのすべてのプロパティが事前に何であるかを知りたくありません。

また、何をチェックしようとしました class プロパティの場合、値を入力する前にコンバージョンを行います(したがって、 [myObject setValue:[NSNumber numberWithInt:[currentElementValue intValue] forKey:elementName]; プロパティの場合 isKindOfClass:[NSNumber class]]. 。これに関する問題は、プロパティが使用されるのはこれが初めてであることです。 nil, 、したがって、クラスがありません。したがって、このアプローチも実際には機能しません。

私はこれを完全に間違っていますか? XMLからデータを取得し、それを非XMLに入れることはかなり典型的なものであるように思われますNSString 変数ですが、私はそれを機能させることができないようです。

誰かがこれがどのように設定されているか、または私がすでに試したことをよりよく理解するために、より多くのコードを見る必要がある場合は、私に知らせてください。


編集:私がやろうとしていることの簡単な例を思いつきました。次のXMLがあるとします。

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

私がのインスタンスに解析したいこと MyObject (an NSObject サブクラス)

@interface MyObject: NSObject

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

@end

2番目の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を使用することは1つの方法です。

ランタイムの詳細を読むことができます マイク・アッシュのブログで または参照してください 客観的なcの内省/反射.

でも、 この特定の問題は、他の多くの人々によって遭遇しました, 、だからかなりの数の解決策があります:で言ったように iOS最も成熟した休憩サービスライブラリ RestKitは、そのようなライブラリの良い例の1つです。 MagicRecordは別です。

独自のソリューションを実装する前に、チェックアウトするライブラリをさらに簡単に見つけることができます。

他のヒント

もちろん、私はただオーバーライドすることができます init の方法 MyObject すべての私のプロパティを空の値に割り当てるために、それは nil 私が自分のOPで参照した問題ですが、それは本当にハッキーだと感じています。ただし、唯一のオプションかもしれません。


編集:このアプローチは、OPの編集の例で完全にバラバラになります。 KVCがターンします intS、 floatBOOLsすべて NSNumberS、彼らが元々どこに何を知るかを知る方法なし。つまり、私は電話することができなくなります [currentElementValue intValue], [currentElementValue floatValue], 、 また [currentElementValue boolValue] 適切に。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top