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;}
|
新聞熱點
疑難解答