iOS开发Foundation中的断言处理

本文介绍了Foundation框架中的断言宏,包括NSAssert/NSCAssert和NSParameterAssert/NSCParameterAssert的区别及其应用场景。此外,还详细解释了NSAssertionHandler的作用及如何自定义断言处理器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Foundation中定义了两组断言的宏,分别是:

    NSAssert / NSCAssert
    NSParameterAssert / NSCParameterAssert

这两组宏主要在功能和语义上有所差别,这些区别主要有以下两点:

  • 1、如果我们需要确保方法或函数的输入参数的正确性,则应该在方法(函数)的顶部使用NSParameterAssert / NSCParameterAssert;而在其它情况下,使用NSAssert / NSCAssert。
  • 2、另一个不同是介于C和Objective-C之间。NSAssert / NSParameterAssert应该用于Objective-C的上下文(方法)中,而NSCAssert / NSCParameterAssert应该用于C的上下文(函数)中。

当断言失败时,通常是会抛出一个如下所示的异常:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'true is not equal to false'

Foundation 为了处理断言,专门定义了一个NSAssertionHandler来处理断言的失败情况。NSAssertionHandler对象是自动创建的,用于 处理失败的断言。当断言失败时,会传递一个字符串给NSAssertionHandler对象来描述失败的原因。每个线程都有自己的 NSAssertionHandler对象。当调用时,一个断言处理器会打印包含方法和类(或函数)的错误消息,并引发一个 NSInternalInconsistencyException异常。就像上面所看到的一样。

我们很少直接去调用NSAssertionHandler的断言处理方法,通常都是自动调用的。

NSAssertionHandler提供的方法并不多,就三个,如下所示:

①
// 返回与当前线程的NSAssertionHandler对象。
// 如果当前线程没有相关的断言处理器,则该方法会创建一个并指定给当前线程
+ (NSAssertionHandler *)currentHandler;
②
// 当NSCAssert或NSCParameterAssert断言失败时,会调用这个方法
- (void)handleFailureInFunction:(NSString *)functionName file:(NSString *)object lineNumber:(NSInteger)fileName description:(NSString *)line, format,...
③
// 当NSAssert或NSParameterAssert断言失败时,会调用这个方法
- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format, ...

另外,还定义了一个常量字符串,主要是用于在线程的threadDictionary字典中获取或设置断言处理器。

NSString * const NSAssertionHandlerKey;

我们可以自定义一个继承自NSAssertionHandler的断言处理类,来实现一些我们自己的需求。如Mattt Thompson的NSAssertionHandler实例一样:

@interface LoggingAssertionHandler : NSAssertionHandler
@end
@implementation LoggingAssertionHandler

- (void)handleFailureInMethod:(SEL)selector
                       object:(id)object
                         file:(NSString *)fileName
                   lineNumber:(NSInteger)line
                  description:(NSString *)format, ...{
    NSLog(@"NSAssert Failure: Method %@ for object %@ in %@#%i", NSStringFromSelector(selector), object, fileName, line);
}
- (void)handleFailureInFunction:(NSString *)functionName
                           file:(NSString *)fileName
                     lineNumber:(NSInteger)line
                    description:(NSString *)format, ...{
    NSLog(@"NSCAssert Failure: Function (%@) in %@#%i", functionName, fileName, line);
}
@end

上面说过,每个线程都有自己的断言处理器。我们可以通过为线程的threadDictionary字典中的NSAssertionHandlerKey指定一个新值,来改变线程的断言处理器。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    NSAssertionHandler *assertionHandler = [[LoggingAssertionHandler alloc] init];
    [[[NSThread currentThread] threadDictionary] setValue:assertionHandler
                                                   forKey:NSAssertionHandlerKey];
    return YES;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoxiaobukuang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值