我刚开始使用iPhone/Objective-C开发,我已经成功地用NSXMLParser解析了XML,但是我不能让异常正常工作。我想使用异常来处理意外的XML。
我包装了用于创建NSXMLParser对象的代码,并将setDelegate和解析消息发送到@try @catch块中的对象,以捕获@NSException。
如果我将NSAssert(FALSE, @"error)放在@try块中,异常就会被正确捕获。然而,如果我在委托调用(例如,didStartElement,didEndElement,foundCharacters)中有一个NSAssert失败,那么程序就死了(在iPhone模拟器中,还没有尝试过设备)。调试器堆栈跟踪显示断言被抛出为异常,但它不会拉回到顶层代码中,在顶层代码中,@try块位于[parser parse]消息调用周围。相反,我得到的是“由于未捕获的异常而终止应用程序”。
如果这是一个已知的问题,或者我在这里做了什么傻事,请让我知道。
谢谢-- Alex
一些代码,以使更具体;没有试图使此代码正确的内存/释放/等。
@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
}发布于 2010-11-23 14:02:48
According to Bill Bumgarner,在iPhone模拟器中捕获异常不能正常工作。你最好的办法就是在这里停止使用异常,因为这并不是很合适。您应该改为调用-[NSXMLParser abortParsing]。
发布于 2010-11-23 15:19:52
不要将异常用于流控制。编写异常安全(重新计数)的Obj-C代码有点痛苦--特别是,像Foo * foo = [[Foo alloc] init]; [foo doStuff]; [foo release]; foo = nil;这样的常用代码会泄漏,[foo lock]; [foo doStuff]; [foo unlock];可能会死锁。你可以通过总是立即自动释放来缓解前者(我总是在重构代码时防止内存泄漏),除非你不能自动释放自动释放池。后者是很难避免的,除非你到处使用@try/@finally。
此外,我强烈建议使用断点objc_exception_throw()。有时,在堆栈被无用地展开之后,当从uncaught_exception_handler() (或其他任何调用)调用abort()时,Xcode似乎错过了抛出的机会,并将您放入调试器中。还有几件事情(特别是CoreAnimation)捕获、记录和忽略异常,这是一个很难调试的过程,除非您关注的是长期的情况。
在应用程序中有一个例子,我为控制流使用了一个异常(我想我给它起的名字是"ControlThrow");每次我碰到那个断点,我都想用一个goto来代替它。
https://stackoverflow.com/questions/4253048
复制相似问题