IOS-Assertion processing and debugging

Source: Internet
Author: User
Tags call back

One, the assertion in Objective-c:
  • The assertion processing in objective-c is using Nsassertionhandler:

    Each thread has its own assertion processor, which is an instance object of the Nsassertionhandler class. When called, an assertion processor prints an error message that contains the method and class name (or function name). Then it throws a Nsinternalinconsistencyexception exception.

  • Two sets of assertion macros are defined in the underlying class
    • Nsassert/nscassert
      /** Nsassert */#if!defined (_nsassertbody)#define NSASSERT (condition, desc, ...) Do {__pragma_push_no_extra_arg_warnings if (!) ( Condition) { NSString *__assert_file__ = [nsstring stringwithutf8string:__file__]; __assert_file__ = __assert_ File__? __ASSERT_FILE__: @ "<unknown file>"; [[Nsassertionhandler Currenthandler] Handlefailureinmethod:_cmd object: Selffile:__assert_file__ lineNumber : __line__ Description: (DESC), # #__VA_ARGS__]; } __pragma_pop_no_extra_arg_warnings} while (0)#endif        
      /** Nscassert */#if!defined (_nscassertbody)#define NSCASSERT (condition, desc, ...)do {__pragma_push_no_extra_arg_warningsif (! ( Condition) {nsstring *__assert_fn__ = [nsstring STRINGWITHUTF8STRING:__PRETTY_FUNCTION__]; __assert_fn__ = __assert_fn__? __ASSERT_FN__: @ "<unknown function>"; nsstring *__assert_file__ = [nsstring stringWithUTF8String : __file__]; __assert_file__ = __assert_file__? __assert_file__: @ "<unknown file>"; [[nsassertionhandler Currenthandler] handlefailureinfunction:__assert_fn__ file:__ assert_file__ linenumber:__line__ Description: (DESC), # #__VA_ARGS__]; } __pragma_pop_no_extra_arg_warnings} while (0)  #endif            
    • nsparameterassert/nscparameterassert
      /** Nsparameterassert */# Define Nsparameterassert (condition) Nsassert  ( (condition), @ "Invalid parameter not satisfying:%@", @ #condition)        
      /** Nscparameterassert */#define NSCPARAMETERASSERTcondition) nscassert ( (condition), @" Invalid parameter not satisfying:%@ ", @ #condition)  
  • The point of doing this is two points:
    • The first one is that Apple differentiates assertion processing at the API level:
      • NSAssertand NSCAssert assertions used to handle the general situation
      • NSParameterAssertWith NSCParameterAssert assertions that are used to handle parameterization
    • The second is that the distinction is between objective-c and C, so only then:
      • NSAssertAndNSCAssert
      • NSParameterAssertAndNSCParameterAssert
Second, the use of Nsassertionhandler
    • Starting with Xcode 4.2, the release build defaults off assertions, which are implemented by defining Ns_block_assertions macros. That is, when compiling the release version, any calls to Nsassert and so on are effectively removed.
      Although the underlying class library assertion macros are useful ———— their own power, they are only used for development. Nsassertionhandler also provides a set of elegant ways to handle assertion failures to preserve valuable real-world usage information.
Pay
attension:

It is said that many experienced objective-c developers caution against using Nsassertionhandler in production environments. The assertion processing in the base class library is used to understand and appreciate outside a certain safe distance. Please be careful if you decide to use it in an external release version of the app.

  • NSAssertionHandleris a straightforward class with two methods that need to be implemented in a subclass: -handleFailureInMethod:... (called when Nsassert/nsparameterassert fails) and -handleFailureInFunction:... (called when Nscassert/nscparameterassert fails).
  • Next look at a used instance
    #pragram The first step, create a class that inherits from Nsassertionhandler: Loggingassertionhandler is used to specifically handle assertions#import<Foundation/Foundation.h>@interfaceLoggingassertionhandler:Nsassertionhandler@end#import"LoggingAssertionHandler.h"@implementationLoggingassertionhandler/** Rewrite two failed callback methods, where we want to throw the error (print or direct error) */-(void) Handlefailureinmethod: (SEL) Selector object: (ID) object File: (NSString *) fileName linenumber: (Nsinteger) Line Description: (NSString *) format, ... {NSLog (@ "Nsassert Failure:method%@ for object%@ in%@#%li", nsstringfromselector (selector), object, FileName, (long) line); nsexception *e = [nsexception exceptionwithname: nsstringfromselector (selector) Reason:format userInfo: nil];  @throw e;} -(void) handlefailureinfunction: (NSString *) functionName File: (nsstring *) fileName linenumber: (nsinteger) line Description: (nsstring *) format, ... {nslog (@ "Nscassert failure:function (%@) in%@#%li", FunctionName, FileName, (long) line);}  @end             
  • Each thread can specify an assertion processor.   To set a Nsassertionhandler subclass to handle failed assertions, set the Nsassertionhandlerkey field in the Threaddictionary object of the thread.

    In most cases, you only need to

    -application:didfinishlaunchingwithoptions:     

    Sets the assertion processor for the current thread.

  • Processing in the appdelegate
    - (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions{NSAssertionHandler *assertionHandler = [[LoggingAssertionHandler alloc] init];[[[NSThread currentThread] threadDictionary] setValue:assertionHandler forKey:NSAssertionHandlerKey];// ...return YES;}
  • So we're done with the configuration of our custom assertion processor in the current thread, and then, if there's a situation that's different from our condition, we can just call back the two failed methods, and we'll be able to handle your words in those two ways, according to our own output intention.
  • Specific applications
    #import "ViewController.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; NSObject*mc = [NSObject new]; mc = @2; NSAssert(mc == nil, @"我不为空了");}@end
    According to the output, we can see that the output is exactly what we need.
    2015-10-30 21:33:14.529 NSAssert[20537:678428] *** Terminating app due to uncaught exception ‘viewDidLoad‘, reason: ‘我不为空了‘
Third, the use of the attention point
  • Looking closely at the macro definition of Nsassert, you will find traces of self, there is self in the place must pay attention to block easy to produce circular reference problem.
    /** Nsassert */#if!defined (_nsassertbody)#define NSASSERT (condition, desc, ...) Do {__pragma_push_no_extra_arg_warnings if (!) ( Condition) { NSString *__assert_file__ = [nsstring stringwithutf8string:__file__]; __assert_file__ = __assert_ File__? __ASSERT_FILE__: @ "<unknown file>"; [[Nsassertionhandler Currenthandler] Handlefailureinmethod:_cmd object: Selffile:__assert_file__ lineNumber : __line__ Description: (DESC), # #__VA_ARGS__]; } __pragma_pop_no_extra_arg_warnings} while (0)#endif        
  • Here's an example:
    /** Create a Preson class */#import<Foundation/Foundation.h>typedefvoid (^mitchelblock) (int num);@interfacePerson:NSObject@property (Nonatomic,copy) Mitchelblock block;@end#import"Person.h"@implementationperson-(instancetype) init{if (Self = [Super Init] {dispatch_after (Dispatch_time (Dispatch_time_now, (int64_t) (2 *NSEC_PER_SEC)), Dispatch_get_main_queue (), ^{if (Self. Block) {Self. Block (1); } }); }ReturnSelf;}@end/** code in Viewcontroller */#import"ViewController.h"#import"Person.h"@interfaceViewcontroller ()@property (Nonatomic,Strong) person * Aperson;@end@implementation viewcontroller-(void) Viewdidload {[super viewdidload]; NSOBJECT*MC = [nsobject new]; MC = @2; self. Aperson = [person new]; self. Aperson. Block = ^ (int num) { Nsassert (mc = = Nil, @ "I am not Empty"); NSLog (@ "%d", num);};} @end                   
    This way we will see a circular reference warning in the Block:

    Screen shot 2015-10-30 pm 9.48.17.png
    What if I want to use assertions in Block? UseNSCAssertReplaceNSAssertNSCParameterAssertTo replaceNSParameterAssert
    - (void)viewDidLoad {  [super viewDidLoad];  NSObject*mc = [NSObject new];  mc = @2; self.aPerson = [person new]; self.aPerson.block = ^(int num){ NSCAssert(mc == nil, @"我不为空了"); NSCParameterAssert(num>5); };}
  • This will be OK.

IOS-Assertion processing and debugging

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.