我正在尝试通过XML解析,我可以从Web服务中获得 NSXMLParserDelegate. 。这 NSObject 我想将数据放入(我只称呼它 MyObject) 有 @property不是 NSStringS(有一些 NSDateS,有些 NSNumbers,也许将来某些原语)。

由于XML都是一个大字符串,因此当我尝试将XML的值直接放入我的属性中时,我会遇到错误并崩溃(我正在使用 [myObject setValue:currentElementValue forKey:elementName]; 在我的 parser:didEndElement:..., ,通常效果很好 - 何时 key 是一个 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中获取数据并将其放入非 - 似乎是相当典型的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];

作为适当的。我打电话给我有很多Web服务,我将获得类似结构化的XML,因此只需要在每个解析器中更改1行,这是非常可取的。在单个“模板”类中,将所有其余的解析器代码都能使维护,读取和调试代码变得更加容易。

显然,我遇到的问题是 isKindOfClass 不接受 int, float, , 或者 BOOL 作为输入。我可以使用类似的东西吗?

有帮助吗?

解决方案

问题在于,这是第一次使用属性,因此它是零,因此没有类。

Objective-C允许 在运行时查询类属性, ,因此内省属性类型并使用适当的TRNSFORMATION是一种方法。

您可以阅读有关运行时的更多信息 在迈克·阿什(Mike Ash)的博客 或看 目标C内省/反射.

然而, 许多其他人已经遇到了这个特定的问题, ,所以有很多解决方案:如 iOS最成熟的休息服务库 RESTKIT是这样一个库的一个很好的例子。 MagicRecord是另一个。

在决定实施自己的解决方案之前,您可以轻松找到更多的库可以退房。

其他提示

当然,我可以覆盖 init 的方法 MyObject 将所有属性分配给空值,这应该解决 nil 我在OP中引用的问题,但这感觉真的很骇人听闻。不过,这可能是唯一的选择。


编辑:这种方法完全散布在OP中的编辑中。 KVC会转 intS, floatBOOL全部 NSNumbers,没有任何方式知道他们最初的地方。这意味着我无法打电话 [currentElementValue intValue], [currentElementValue floatValue], , 或者 [currentElementValue boolValue] 作为适当的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top