异常的捕捉
// @try 块捕捉异常
@try {
// 这里发生了一个异常
@throw [NSException exceptionWithName:@"demo" reason:@"the exception demo" userInfo:nil] ;
}
@catch (NSException *exception) {
// 输出异常详细原因
NSLog([exception reason]);
// 输出异常名称
NSLog([exception name]) ;
// @throw ; // 再次将异常抛出,@catch 块中@throw 未指定欲抛出的异常指针则默认抛出@catch 的参数.
}
@catch(id exception){
// 处理其他异常
}
@finally {
}
@catch 块中抛出异常,若@throw 未指定欲抛出的异常指针则默认抛出@catch 的参数. 上处代码的catch块则会抛出 exception
异常所带来的内存管理问题
//不捕获异常的内存管理
Person *p = [[Person alloc] init];
[p description] ;
[p release] ;
// 捕获异常的内存管理
Person *p2 = [[Person alloc] init ] ;
@try {
[p2 description] ;
}
@catch (NSException *exception) {
NSLog(@"exception : %@" ,[exception reason]) ;
}
@finally {
[p2 release];
}
异常和自动释放池
异常处理有时候会遇到异常对象被自动释放的小问题,因为你不知道什么时候释放异常对象,所以它总是作为自动释放对象而创建。当自动释放池销毁的时候,自动释放池中托管的所有对象也会被销毁,其中包括异常对象。
观察如下代码。
-(void) test{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init ];
@try {
// 此处会发生异常
NSDictionary *myDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:@"asdasd", nil];
}
@catch (NSException *exception) {
// @throw 会在finally 之后执行,这个时候 exception 已经被release。
@throw ;
}
@finally {
[pool release] ;
}
}
上述代码看似正确,但别高兴的太早,@catch代码块中再次抛出异常,而@fianlly 则会在@throw 之前执行,这样会导致pool被释放,而在pool中托管着异常对象,则异常对象exception也会被释放。在外部使用这个exception的时候就会发生异常。
解决办法: 在pool外部保留
-(void) test{
// 用于保存exception
id saveException = nil ;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init ];
@try {
// 此处会发生异常
NSDictionary *myDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:@"asdasd", nil];
}
@catch (NSException *exception) {
// retain 一下再throw 确保对象不会被释放
saveException = [exception retain];
@throw ;
}
@finally {
[pool release] ;
// 保留下来的exception 也需要释放,当外部pool release的时候才会被释放
[saveException autorelease ];
}
}
XCode禁用异常。
选择项目的属性文件 --》 搜索Exception --> Enable Objective-C Exceptions --> 选择NO
时间: 2024-10-10 21:44:45