NSXML在NSXMLParser委托中没有被捕获

时间:2010-11-23 05:25:35

标签: iphone ios try-catch nsxmlparser

我是iPhone / Objective-C开发的新手,我使用NSXMLParser成功解析XML但我无法获得正常工作的异常。我想使用异常来处理意外的XML。

我正在包装用于创建NSXMLParser对象的代码,并将setDelegate和parse消息发送到@try @catch块内的对象,捕获@NSException。< / p>

如果我将NSAssert(FALSE, @"error)放在@try块中,则会正确捕获异常。但是,如果我在委托调用中遇到NSAssert失败(例如didStartElementdidEndElementfoundCharacters),那么程序就会死掉(在iPhone模拟器中,避风港)尝试了设备)。调试器堆栈跟踪显示断言被引发到异常,但它不会退回到@try块围绕[parser parse]消息调用的顶级代码。相反,我得到“由于未捕获的异常而终止应用程序。”

如果这是一个已知问题或者我在这里做些蠢事,请告诉我。

谢谢 - 亚历克斯

一些更具体的代码;没有尝试使这段代码正确用于内存/发布/等。

@implementation XMLTester

+(void)runXMLTester
{
    BOOL success = FALSE;
    XMLTester *tester = [[XMLTester alloc] init];
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml?query=KSFO"]];
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
    [parser setDelegate:tester];
    @try {
        //NSAssert(FALSE, @"error"); // this assertion works fine
        success = [parser parse];
    }
    @catch (NSException * e) {
        success = FALSE;
        NSLog(@"Exception caught %@: %@", [e name], [e reason]);
    }
    @finally {
        NSLog(@"runXMLTester @finally block hit");
    }
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
    NSLog(@"Starting element %@", elementName);
    NSAssert(FALSE, @"error"); // this assertion does not work - does not hit @try block around parse message
}

2 个答案:

答案 0 :(得分:0)

According to Bill Bumgarner,在iPhone模拟器中捕获异常无法正常工作。你最好的办法是在这里停止使用例外,因为它无论如何都不合适。您应该改为呼叫-[NSXMLParser abortParsing]

答案 1 :(得分:0)

不要使用异常进行流量控制。编写异常安全(refcounted)的Obj-C代码有点痛苦 - 特别是像Foo * foo = [[Foo alloc] init]; [foo doStuff]; [foo release]; foo = nil;这样常用的东西会泄漏,[foo lock]; [foo doStuff]; [foo unlock];可能会死锁。您可以通过始终自动释放来缓解前者(我总是在重构代码时防止内存泄漏),除非您无法自动释放自动释放池。后者很难避免,除非你把@ try / @最后撒在

此外,我强烈建议使用breakjinting objc_exception_throw()。有时Xcode似乎错过了抛出,并且在堆栈被无益地解开后从uncaught_exception_handler()(或其他任何调用的方法)调用abort()时,您将进入调试器。还有一些东西(特别是CoreAnimation)捕获,记录和忽略异常,这是一个很难调试,除非你看很长时间。

在应用程序中有一个案例,我使用控件流的异常(我想我给它起了名字“ControlThrow”);每当我点击那个断点时,我都很想用goto替换它。