The cause of iOS Crash is that the application receives unprocessed signals, which may come from three sources: kernel(system kernel), other processes, and App itself. Therefore, Crash anomalies can also be divided into three types:

  • Mach exceptions: These are the lowest level kernel-level exceptions. User developers can catch Mach exceptions by setting exception ports for Thread, task, and host directly through the Mach API.
  • Unix signals: Also known as BSD signals, if the developer does not catch a Mach exception, the exception is converted to the corresponding Unix signal by the host layer method ux_Exception () and sent to the error thread via the threadSignal () method. Single can be caught using the method Signal (x, SignalHandler).
  • NSException: Application-level exceptions, which are objective-C exceptions that are not caught, cause the program to send itself a SIGABRT signal and crash. For uncaught Objective-C exceptions, you can catch them by try catch. Or by NSSetUncaughtExceptionHandler (doesn’t stop the program crashes, namely the collapse or collapse, we can do is statistical records here such as operation) mechanism to capture. IOS crash classification,Mach exception, Unix signal and NSException exception

Let’s start with the most familiar NSException.

NSException

System exception handling is the process of managing atypical events (such as unrecognized messages being sent) that interrupt the normal program execution flow. Without adequate error handling, when an atypical event is encountered, the program may immediately throw or throw a behavior called an exception that ends the program’s normal operation. A program throws exceptions for a variety of reasons, from hardware to software. Examples of exceptions are numerous, including mathematical errors such as division by zero, overflows and overflows, calls to undefined instructions (for example, trying to call an undefined method), and attempts to access elements in a collection out of bounds. And the NSException object is as an exception carrier, remind us of the cause of the exception as well as the function call stack information and other important information, to help us more quickly repair the code caused by the exception. NSException Exception processing

Class NSException (NSException)

The NSException class is a subclass of NSObject used in Cocoa to describe the special case (cause) of interrupting the normal flow of program execution, that is, to describe the reason why the normal execution of the program was interrupted. (An object that represents a special condition that interrupts the normal flow of program execution.)

Declaration

#if __OBJC2__
__attribute__((__objc_exception__))
#endif
@interface NSException : NSObject <NSCopying, NSSecureCoding> {
    @private
    NSString        *name;
    NSString        *reason;
    NSDictionary    *userInfo;
    id            reserved;
}
Copy the code

The reserved field is a reserved field of type ID. Although it is reserved, it is currently used as a mutable dictionary type to store callStackReturnAddresses and callStackSymbols. Is the function call stack data that we care about most when our program crashes.

Overview

Implement exception handling (description) using NSException. An exception is a special case that interrupts the normal flow of program execution. Each process can be interrupted for different reasons. For example, an application might interpret the file being in a write-protected directory as an exception. In this sense exception is equivalent to an error. Another application might interpret a user’s keystroke, such as Control + C, as an exception: an indication that a long-running process should be aborted.

Creating and Raising an NSException Object

+ exceptionWithName:reason:userInfo:

typedef NSString * NSExceptionName NS_EXTENSIBLE_STRING_ENUM;

+ (NSException *)exceptionWithName:(NSExceptionName)name
                            reason:(nullable NSString *)reason
                          userInfo:(nullable NSDictionary *)userInfo;
Copy the code

Create and return an Exception object. Name: the name of an NSString exception. Reason: a human-readable message string summarizing the reason for exception. UserInfo: a dictionary containing user-defined information related to exception. The return value is an NSException object, or nil if it cannot be created.

+ raise:format:


@interface NSException (NSExceptionRaisingConveniences)

+ (void)raise:(NSExceptionName)name format:(NSString *)format, ... NS_FORMAT_FUNCTION(2.3);. @endCopy the code

A convenience function that creates an NSException object and throws (throws) exception directly. Name: the name of an NSString exception, format: a human-readable message string (that is, the reason for the exception), with the conversion specification for the variable argument that follows.

[NSException raise:@"EXCEPTION_NAME" format: @"异常 reason: %@"The @"Test directly raises an exception", nil];
Copy the code

For example, if you write the above code in the viewDidLoad function, after running the program, the program will crash, and the console will print the following information:

*** Terminating app due to uncaught exception 'EXCEPTION_NAME', reason: 'Exception reason: Test introduces an exception'. (Call stack omitted...)Copy the code

+ raise:format:arguments:

@interface NSException (NSExceptionRaisingConveniences). +(void)raise:(NSExceptionName)name format:(NSString *)format arguments:(va_list)argList NS_FORMAT_FUNCTION(2.0);

@end
Copy the code

As above, append parameters in different ways.

– initWithName:reason:userInfo:

- (instancetype)initWithName:(NSExceptionName)aName
                      reason:(nullable NSString *)aReason
                    userInfo:(nullable NSDictionary *)aUserInfo NS_DESIGNATED_INITIALIZER;
Copy the code

Initialize and return the newly allocated Exception object.

– raise

- (void)raise;
Copy the code

Throw (or throw) exception, causing the program flow to jump to the local exception handler (void uncaughtExceptionHandler(NSException *exception) function, which we’ll learn more about later).

During development, when certain business logic conditions are not met, we can create an NSException object and then call the raise function to throw an exception directly to help us find the problem, or in a try catch statement, when we receive an exception that we didn’t expect, In the catch statement we continue to call the raise function to throw an exception so that we can find some unknown problems.

When there are no exception handlers in the exception handler stack unless the exception is raised during the posting of a notification, this method calls the uncaught exception handler, in which last-minute logging can be performed. The program then terminates, regardless of the actions taken by the uncaught exception handler.

When there is no exception handler in the exception handler stack, this method call does not catch an exception handler (void uncaughtExceptionHandler(NSException * Exception)) unless an exception is thrown during the notification period, Last minute logging can be performed in this handler (it can take a long time, well over a minute, seemingly as long as the function content is not finished). Whatever uncaughtExceptionHandler does, the program terminates.

Querying an NSException Object

name

typedef NSString * NSExceptionName NS_EXTENSIBLE_STRING_ENUM;

@property (readonly, copy) NSExceptionName name;
Copy the code

A read-only string representing the name of the NSException object for unique identification.

Cocoa defines some generic exception names in advance to identify exceptions that can be handled in your own code, and even to raise and re-raise exceptions (e.g., to catch an exception in a try-catch, or to continue to throw an exception when it is unknown, using the @throw or raise functions). You can also create and use custom exception names. The usual exception name is a string constant defined in NSException. H, documented in Foundation Constants Reference. In addition to the general exception names, some of the Cocoa subsystem also defines its own unusual names, such as NSInconsistentArchiveException and NSFileHandleOperationException. By comparing the name of the exception to these predefined names, you can identify and catch exceptions in the exception handler. You can then handle the exception or, if it’s not of interest to you, rethrow it. Note that all predefined exceptions start with the prefix “NS”, so you should avoid using the same prefix when creating new exception names (avoid having the same name as those predefined exceptions). Predefined Exceptions

At the top of the NSException. H file, a set of predefined exception names is listed to help us categorize common exceptions thrown.

/*************** Generic Exception names ***************/

FOUNDATION_EXPORT NSExceptionName const NSGenericException;
FOUNDATION_EXPORT NSExceptionName const NSRangeException;
FOUNDATION_EXPORT NSExceptionName const NSInvalidArgumentException;
FOUNDATION_EXPORT NSExceptionName const NSInternalInconsistencyException;

FOUNDATION_EXPORT NSExceptionName const NSMallocException;

FOUNDATION_EXPORT NSExceptionName const NSObjectInaccessibleException;
FOUNDATION_EXPORT NSExceptionName const NSObjectNotAvailableException;
FOUNDATION_EXPORT NSExceptionName const NSDestinationInvalidException;
    
FOUNDATION_EXPORT NSExceptionName const NSPortTimeoutException;
FOUNDATION_EXPORT NSExceptionName const NSInvalidSendPortException;
FOUNDATION_EXPORT NSExceptionName const NSInvalidReceivePortException;
FOUNDATION_EXPORT NSExceptionName const NSPortSendException;
FOUNDATION_EXPORT NSExceptionName const NSPortReceiveException;

FOUNDATION_EXPORT NSExceptionName const NSOldStyleException;

FOUNDATION_EXPORT NSExceptionName const NSInconsistentArchiveException;
Copy the code

Let’s look at the names of this set of NSException. NSRangeException is probably the most familiar. The name of the object that causes an exception when an array is accessed out of bounds is NSRangeException. Here’s a quick list of the different NSExceptionName exceptions that cause them.

NSGenericException
FOUNDATION_EXPORT NSExceptionName const NSGenericException;
Copy the code

NSGenericException is a generic name for exception, and usually we should use the more specific name of exception to indicate the exception that occurs.

  1. Add and remove elements in the for in loop:*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x600003764450> was mutated while being enumerated.' Exception: iOS array NSGenericException, Collection < __NSArrayM: 0 x61800024f7b0 > was mutated while being enumerated. ‘
  2. When I use UIActivityViewController, Under the object must be to create UIActivityViewController. PopoverPresentationController. SourceView attribute assignment, otherwise it will crash, the iPhone is not:*** Terminating app due to uncaught exception 'NSGenericException', reason: 'UIPopoverPresentationController (<UIPopoverPresentationController: 0x7fe9c95144f0>) should have a non-nil sourceView or barButtonItem set before the presentation occurs.'.
  3. NSURLSessionTaskMetrics _initWithTask on iOS 10.0-10.2*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Start date cannot be later in time than end date! '. It has been a long time since then. Please refer to this link to describe it clearly:IOS10 crash fix — NSURLSessionTaskMetrics
  4. .
NSRangeException
FOUNDATION_EXPORT NSExceptionName const NSRangeException;
Copy the code

The name of the exception that occurs when you try to access some data outside the boundary. (e.g., outside the end of a string)

  1. The most common out-of-bounds access to arrays you see:*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndexedSubscript:]: index 3 beyond bounds [0 .. 2]'
NSInvalidArgumentException
FOUNDATION_EXPORT NSExceptionName const NSInvalidArgumentException;
Copy the code

The name of the exception that occurs when an invalid argument is passed to a method, such as a nil pointer when a non-nil object is needed.

Illegal abnormal parameters (NSInvalidArgumentException) is a particularly common abnormalities, we need to heed the inspection parameters when writing code, to avoid the incoming lead to abnormal illegal parameters, especially for passing nil arguments lead to abnormal.

Here are a few things to be aware of when working with the collection types: NSMutableDictionary, NSMutableArray, and NSDictionary:

  • NSMutableDictionary adds an object:
  1. - (void)setObject:(ObjectType)anObject forKey:(KeyType <NSCopying>)aKey;

Function call anObject and aKey cannot is nil, abnormal NSInvalidArgumentException otherwise occur. *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[__NSDictionaryM setObject:forKey:]: object cannot be nil (key: key)’ *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[__NSDictionaryM setObject:forKey:]: key cannot be nil’

  1. - (void)setValue:(nullable ObjectType)value forKey:(NSString *)key;

Function calls the key not to nil, otherwise NSInvalidArgumentException anomalies occur, the value can be nil, when the value is nil, calls – removeObjectForKey:. Function to delete the specified key. (Send-set object :forKey: to the receiver, unless the value is nil, in which case send-removeObjectForkey :.) *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[__NSDictionaryM setObject:forKey:]: key cannot be nil’

  1. - (void)setObject: nullable ObjectType obj forKeyedSubscript: KeyType <NSCopying> Key API_AVAILABLE(macOS (10.8), Ios (6.0), watchos (2.0), tvos (9.0));Function callobjCannot be nil (keyNSInvalidArgumentException anomaly can be nil), otherwise occur.

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSDictionaryM setObject:forKeyedSubscript:]: key cannot be nil'

  • NSMutableDictionary deletes objects:
  1. - (void)removeObjectForKey:(KeyType)aKey;

Function call aKey cannot is nil, otherwise occur NSInvalidArgumentException anomalies. *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[__NSDictionaryM removeObjectForKey:]: key cannot be nil’

  • NSDictionary initialization:
  1. + (instancetype)dictionaryWithObject:(ObjectType)object forKey:(KeyType <NSCopying>)key;

Function call object and key cannot is nil, otherwise NSInvalidArgumentException anomalies. *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]’

  1. + (instancetype)dictionaryWithObjects:(NSArray<ObjectType> *)objects forKeys:(NSArray<KeyType <NSCopying>> *)keys;

Function call objects and keys two arrays must have equal number of elements, otherwise NSInvalidArgumentException anomalies. *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[NSDictionary initWithObjects:forKeys:]: count of objects (1) differs from count of keys (2)’

  1. + (instancetype)dictionaryWithObjectsAndKeys:(id)firstObject, ... NS_REQUIRES_NIL_TERMINATION NS_SWIFT_UNAVAILABLE("Use dictionary literals instead");When the function is called,(id)firstObject, ...Arguments are a variable number of arguments, and they are used in pairs, ending with nil, and then a consecutive pair of arguments, with the first value used as value and the second value used as key. Value comes first, it combines with the first key that comes after it into a key-value pair and it’s inserted into the NSDictionary, and it ends when it hits the first nil parameter, so key can’t be nil, Otherwise NSInvalidArgumentException anomalies occur, and the value is nil will be treated as NSDictionary build end tag.

*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘+[NSDictionary dictionaryWithObjectsAndKeys:]: second object of each pair must be non-nil. Or, did you forget to nil-terminate your parameter list? ‘due to the previous value is nil when NSDictionary build end ahead of schedule, so we may encounter this kind of circumstance: careful dictionaryWithObjectsAndKeys:

  • NSArray gets the matching subscript:
  1. - (NSUInteger)indexOfObject:(ObjectType)obj inSortedRange:(NSRange)r options:(NSBinarySearchingOptions)opts UsingComparator :(NSComparator NS_NOESCAPE) CMP API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)); // binary searchReturns the index of the object in the specified NSRange compared to elements in the array using the given NSComparator block. None of the arguments to this function can be null:

obj An object for which to search in the ordered set. If this value is nil, throws an NSInvalidArgumentException. range The range within the array to search for object. If r exceeds the bounds of the ordered set (if the location plus length of the range is greater than the count of the ordered set), throws an NSRangeException. cmp A comparator block used to compare the object obj with elements in the ordered set. If this value is NULL, throws an NSInvalidArgumentException.

  • Sends a message to every object in NSArray
  1. – (void)makeObjectsPerformSelector:(SEL)aSelector; This method raises the an NSInvalidArgumentException if aSelector is NULL. The aSelector cannot be NULL, An abnormal NSInvalidArgumentException otherwise occur. ASelector cannot pass parameters and has no side effects of modifying the original array.

  2. – (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)argument; Same as above, but to preach, but again, aSelector cannot be NULL, or send a NSInvalidArgumentException anomalies.

  • (NSArray/NSMutableArray) adding to an array object, the object is not nil, otherwise a NSInvalidArgumentException anomalies
  1. - (NSArray<ObjectType> *)arrayByAddingObject:(ObjectType)anObject;
  2. - (void)addObject:(ObjectType)anObject;
  • NSMutableArray inserts objects
  1. - (void)insertObject:(ObjectType)anObject atIndex:(NSUInteger)index;If anObject is nil, one occursNSInvalidArgumentExceptionException, if index is greater than the number of elements in NSMutableArrayNSRangeExceptionThe exception.
  • NSMutableArray replaces the object
  1. - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(ObjectType)anObject;The same overstepping the markNSRangeException, if one is nil, it is reportedNSInvalidArgumentExceptionThe exception.
  • NSMutableArray Sets the object
  1. - (void)setObject:(ObjectType)obj atIndexedSubscript:(NSUInteger)idx;The same overstepping the markNSRangeException, if one is nil, it is reportedNSInvalidArgumentExceptionThe exception.
  • Nsstrings initialization
  1. - (instancetype)initWithString:(NSString *)aString; Raises an NSInvalidArgumentException if aString is nil.
  • NSString format initialization
  1. - (instancetype)initWithFormat:(NSString *)format, ... ; Raises an NSInvalidArgumentException if format is nil.
  • NSString Initializes other NSString objects
  1. + (instancetype)stringWithString:(NSString *)string; Raises an NSInvalidArgumentException if aString is nil.

  2. - (NSString *)stringByAppendingString:(NSString *)aString; Raises an NSInvalidArgumentException if aString is nil.

  • NSMutableString format initialization
  1. - (void)appendFormat:(NSString *)format, ... ; Raises an NSInvalidArgumentException if format is nil.
  • NSMutableString replacement operation
  1. - (NSUInteger)replaceOccurrencesOfString:(NSString *)target withString:(NSString *)replacement options:(NSStringCompareOptions)options range:(NSRange)searchRange;Three of these parameters can cause different exceptions.

Raises an NSInvalidArgumentException if target is nil. Raises an NSInvalidArgumentException if replacement is nil. Raises an NSRangeException if any part of searchRange lies beyond the end of the receiver.

  • Determine the prefix and suffix of NSString
  1. - (BOOL)hasPrefix:(NSString *)str; *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString hasPrefix:]: nil argument'

  2. - (BOOL)hasSuffix:(NSString *)str; *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString hasSuffix:]: nil argument'

  • Storyboard or.xib loaded, corresponding file name does not exist
  1. *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Could not find a storyboard named 'Main' in bundle NSBundle </Users/hmc/Library/Developer/CoreSimulator/Devices/2ADFB467-5FFF-4F61-872F-73F1CF1C2174/data/Containers/Bundle/Applicat ion/1DE87EF5-E2FA-44B8-8967-F565941653CB/dSYMDemo.app> (loaded)'
NSInternalInconsistencyException
FOUNDATION_EXPORT NSExceptionName const NSInternalInconsistencyException;
Copy the code

The name refers to an “internally contradictory” exception, the name of an exception that occurs when an internal assertion fails, and implies an unexpected condition in the invoked code. Name of an exception that occurs when an internal assertion fails and implies an unexpected condition within the called code.

  1. Mutating method sent to immutable object. (For example, a function call returns an NSDictionary object, uses an NSMutableDictionary pointer variable to receive it, and then makes some changes to the object as a mutable dictionary. Test code now NSInvalidArgumentException anomalies, and is no longer NSInternalInconsistencyException anomalies. IOS NSInternalInconsistencyException Crash)
  2. Manually createUIApplicationObject:UIApplication *app = [[UIApplication alloc] init];See,UIApplicationinitThe function fires an assertion and then reports oneNSInternalInconsistencyExceptionThe exception. This should be a little bit understandable, but in the current process, UIApplication is used as a singleton class, and when the App starts, the system automatically builds a UIApplication object that represents the current process.

*** Assertion failure in -[UIApplication init], UIApplication.m:1469 *** Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘There can only be one UIApplication instance.’ NSInternalInconsistencyException 3. Specifies to refresh the tableView beyond the current section and row scope. See the UITableView _endCellAnimationsWithContext function triggered assertions, and then offered a NSInternalInconsistencyException anomalies. The reason: When reloadRowsAtIndexPaths is called, the cell to be updated depends on the previous state of the tableView. It deletes the cell first and then creates it again. So when you call reloadRowsAtIndexPaths in a state where the cell did not exist, you will get an exception that you are trying to delete a cell that does not exist. ReloadData is completely reloaded, including the number of cells, and does not depend on the previous state of the tableView. IOS call reloadRowsAtIndexPaths Crash report abnormal NSInternalInconsistencyException * * * an Assertion failure in – [UITableView _endCellAnimationsWithContext:], UITableView.m:2097 *** Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘attempt to delete row 6 from section 0 which only contains 5 rows before the update’

NSMallocException
FOUNDATION_EXPORT NSExceptionName const NSMallocException;
Copy the code

Obsolete; Not currently used. It is used to represent the problem of insufficient memory, unable to allocate enough memory, such as the size of memory to be allocated is an abnormal value, is too large, or the device is out of memory and is used up. Deprecated, but some of our examples of incorrect code can trigger an exception with this name, as follows: iOS Crash NSMallocException

  1. Too much space to allocate.
NSMutableData *data = [[NSMutableData alloc] initWithCapacity:1];
long long len = 203293514220329351;
[data increaseLengthBy:len];
Copy the code

*** Terminating app due to uncaught exception ‘NSMallocException’, reason: ‘Failed to grow buffer’.

  1. Images take up too much space and there are OOM (Out of memory) issues.
NSObjectInaccessibleException
FOUNDATION_EXPORT NSExceptionName const NSObjectInaccessibleException;
Copy the code

The name of the exception that occurs when a remote object is accessed by a thread that should never access it. Name of an exception that occurs when a remote object is email exchange with a thread that should not access it. Not yet.)

NSObjectNotAvailableException
FOUNDATION_EXPORT NSExceptionName const NSObjectNotAvailableException;
Copy the code

Name of an exception that occurs when the remote side of the NSConnection refused to send the message to the object because the object has never been vended.

  1. *** Terminating app due to uncaught exception 'NSObjectNotAvailableException', reason: 'UIAlertView is deprecated and unavailable for UIScene based applications, please use UIAlertController! '
NSDestinationInvalidException
FOUNDATION_EXPORT NSExceptionName const NSDestinationInvalidException;
Copy the code

Name of an exception that occurs when an internal assertion fails and implies an unexpected condition within the Distributed Objects. This is a distributed Objects-specific exception. (The name of the exception that occurs when an internal assertion fails, indicating an unexpected condition in distributed Objects. This is a distributed object specific exception.

NSPortTimeoutException
FOUNDATION_EXPORT NSExceptionName const NSPortTimeoutException;
Copy the code

Name of an exception that occurs when a timeout set on a port expires during a send or receive operation Distributed objects – specific exception.

NSInvalidSendPortException
FOUNDATION_EXPORT NSExceptionName const NSInvalidSendPortException;
Copy the code

Name of an exception that occurs when the send port of an NSConnection has become invalid. This is a distributed Objects – specific exception.

NSInvalidReceivePortException
FOUNDATION_EXPORT NSExceptionName const NSInvalidReceivePortException;
Copy the code

Name of an exception that occurs when the receive port of an NSConnection has become invalid. This is a distributed Objects – specific exception.

NSPortSendException
FOUNDATION_EXPORT NSExceptionName const NSPortSendException;
Copy the code

Generic Error occurred on send.This is an nsport-specific exception.

NSPortReceiveException
FOUNDATION_EXPORT NSExceptionName const NSPortReceiveException;
Copy the code

Generic Error occurred on receive.This is an nsport-specific exception.

NSOldStyleException
FOUNDATION_EXPORT NSExceptionName const NSOldStyleException;
Copy the code
NSInconsistentArchiveException
FOUNDATION_EXPORT NSExceptionName const NSInconsistentArchiveException;
Copy the code

The name of an exception raised by NSArchiver if there are problems initializing or encoding.

reason

@property (nullable, readonly, copy) NSString *reason;
Copy the code

A read-only string, possibly nil, a human-readable string that is used to indicate why exception occurred. Such as our common an array access error printing: * * * – [__NSArrayI objectAtIndexedSubscript:] : index 3 beyond bounds [0.. 2].

One more small detail, NSException class – (NSString *)description {… } simply returns the reason attribute of the instance object, such as NSLog(@”🐝🐝🐝 exception: %@”, exception); Just print the value of exception.reason.

userInfo

@property (nullable, readonly, copy) NSDictionary *userInfo;
Copy the code

A read-only NSDictionary, possibly nil, that contains application-specific data associated with the Exception object.

Nil if no application-specific data exists. For example, if the return value of a method causes an exception to be thrown, the return value might be available to an exception handler through that method.

Getting Exception Stack Frames

callStackReturnAddresses

@property (readonly, copy) NSArray<NSNumber *> *callStackReturnAddresses API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
Copy the code

Call return addresses associated with the thrown exception.

CallStackReturnAddresses is an array of NSNumber objects whose elements are integer values (Po prints decimal integers). Each value is the return address of a call frame (that is, each function in the function call stack). The stack Frames array starts at the point where the exception was first raised. The first item is the most recent stack frame. (This information may not be available to subclasses of NSException or subclasses that interfere with the exception throwing mechanism, or other API elements that pretend to be subclasses of NSException class.)

callStackSymbols

@property (readonly, copy) NSArray<NSString *> *callStackSymbols API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
Copy the code

Returns an array containing the call stack symbol when the current exception was thrown.

An array containing call stack symbols. Each element is an NSString object whose value format is determined by the backtrace_symbols() function.

The return value describes the call stack traceback of the current thread when this method was called.

CallStackSymbols and callStackReturnAddresses are stored in the Reserved field of the Exception object. We are familiar with the contents of the three fields crash, name, reason and userInfo. Then we focus on the reserved field. It can be seen that it is a mutable dictionary with two keys: CallStackReturnAddresses and callStackSymbols, whose value is an array of length 17, respectively, that holds the return address of the call stack and the symbols of the call stack.

Related Types

NSUncaughtExceptionHandler

// In Developer Documentation it looks like this:
typedef void (NSException * _Nonnull) NSUncaughtExceptionHandler;

// In NSException. H
typedef void NSUncaughtExceptionHandler(NSException *exception);
Copy the code

To the return value is the void into the parameter is a function of NSException pointer (not empty) up a NSUncaughtExceptionHandler alias.

NSExceptionName

typedef NSString *NSExceptionName;
Copy the code

The name of the exception is actually of type NSString.

Functions

NSGetUncaughtExceptionHandler

NSUncaughtExceptionHandler * NSGetUncaughtExceptionHandler(void);
Copy the code

Returns the current top-level exception handler.

Returns a NSUncaughtExceptionHandler function pointer to the top – level error – handling function, when the exception thrown on execution is terminated before will call this function, we can add abnormal records, Write the abnormal information locally and send it to the server for statistics when the APP starts next time. (by default NSUncaughtExceptionHandler the return value is empty, we need to call NSSetUncaughtExceptionHandler function set in advance.)

NSSetUncaughtExceptionHandler

FOUNDATION_EXPORT void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler * _Nullable);
Copy the code

Changes (sets) the current top-level exception handler.

All uncaught exceptions should be either grabbed or statistically uploaded for feedback and monitoring of program execution. We can use in the OC @ the try @ catch statement to catch exceptions, and an uncaught exception we still have a chance to unified handling, we can use NSSetUncaughtExceptionHandler to set this function.

    @try {
        // Possible exception code
    } @catch (NSException *exception) {
        // If the object does not exist
        if ([exception.name isEqualToString:NSObjectInaccessibleException]) {
            NSLog(@"Object have not exits");
        } else {
            // Throw to an unhandled exception function. You can use raise or @throw to continue throwing exceptions
            [exception raise];
// @throw exception;
        }
    } @finally {
        // 
    }
Copy the code

First write a NSUncaughtExceptionHandler types of functions:

void uncaughtExceptionHandler(NSException *exception) {
    NSArray *stackSymbols = [exception callStackSymbols];
    NSArray *stackReturnAddress = [exception callStackReturnAddresses];
    
    NSString *crashReportString = [NSString stringWithFormat:@"Exception report :\ nName :%@\ nReason :%@\ncallStackSymbols:\n%@\nstackReturnAddress:\n%@", [exception name], [exception reason], [stackSymbols componentsJoinedByString:@"\n"], [stackReturnAddress componentsJoinedByString:@"\n"]].NSLog(@"🏵 🏵 🏵 crashReportString: % @", crashReportString);
    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"Exception.txt"];
    [crashReportString writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
Copy the code

And then we call NSSetUncaughtExceptionHandler function set uncaughtExceptionHandler to unified uncaught exception handling function. There is another point, if we call NSSetUncaughtExceptionHandler before, there have been other third party introduced SDK installed uncaught exception handler, we before setting will override Settings (or our own set up later, By a third party SDK set again, causing it to set our own uncaught exception handler that covered), so we can use NSGetUncaughtExceptionHandler to get the current uncaught exception handler, recorded with a function pointer, We then call the original exception handler again in our newly set uncaught exception handler.

void originalUncaughtExceptionHandler(NSException *exception);

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    NSUncaughtExceptionHandler *currentHandler = NSGetUncaughtExceptionHandler(a);NSLog(@"✳️✳️✳️ current uncaught exception handler: %p", currentHandler);
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    
    return YES;
}
Copy the code

Refer to the link

Reference link :🔗

  • IOS NSInvalidArgumentException Crash
  • IOS call reloadRowsAtIndexPaths Crash abnormal NSInternalInconsistencyException
  • The quality of iOS development
  • NSException throws an exception &NSError
  • NSException: Error handling mechanism – how to collect error logs for products during debugging and after launch
  • Exception Programming Topics
  • IOS developers forget about NSException- it’s powerful
  • IOS Runtime Features and common crashes say bye!
  • Use of Exception Handling NSException
  • Exception statistics – IOS collects crash information NSEXCEPTION class
  • NSException Exception processing
  • IOS NSGenericException Crash
  • IOS Exception Handling
  • IOS Exception Handling
  • IOS crash classification,Mach exception, Unix signal and NSException exception