One of iOS apps-exception handling (Uncaughtexceptionhandler)

Source: Internet
Author: User

Use reason

In the development of iOS, we will encounter the case that the program throws an abnormal exit, and if it is in the process of debugging, the information of the exception is clear at a glance, but it is sometimes difficult to get the information of the exception in the published program.

Advantages and Disadvantages

iOS provides an exception to the processing API, we can add such a handler when the program starts, such a program when an exception can be done in this part of the information necessary processing, timely feedback to the developer.

The disadvantage is that not all of the program crashes are due to the occurrence of the exception can be caught, sometimes because of memory and other errors caused the program crashes, such information is not reflected here.

Common ways of handling

The first way: for basic operations, you can add and get handler, capture the exception and write the information to exception. TXT under the app's Documens.

The second way: for example, you can read this exception file to the server at the time of the next time the program comes up.

The Third Way: or directly in the processing code with OpenURL (mailto:) Call the way to send the message, the exception information directly into the message sent to the specified address, there are many ways to deal with.

Instance:

#pragma the notation in the Mark proxy class

-(BOOL) Application: (UIApplication *) application didfinishlaunchingwithoptions: (Nsdictionary *) launchOptions {

[Window makekeyandvisible];
[Nduncaughtexceptionhandler Setdefaulthandler];
Nsarray *array = [Nsarray arraywithobject:@ "There is only one objective in this Arary,call index one, app'll crash and T Hrow an exception! "];
NSLog (@ "%@", [array objectatindex:1]);

return YES;
}

Exception Basic Interface display:

#import <Foundation/Foundation.h>

@interface Nduncaughtexceptionhandler:nsobject {

}

+ (void) Setdefaulthandler;
+ (nsuncaughtexceptionhandler*) gethandler;

@end
You can also choose to set a custom handler to allow the user to select

Interface implementation Display
#import "NdUncaughtExceptionHandler.h"

NSString *applicationdocumentsdirectory () {
return [Nssearchpathfordirectoriesindomains (NSDocumentDirectory, Nsuserdomainmask, YES) lastobject];
}

void Uncaughtexceptionhandler (NSException *exception) {
Nsarray *arr = [exception callstacksymbols];
NSString *reason = [exception reason];
NSString *name = [exception name];

NSString *url = [NSString stringwithformat:@ "============= exception crash report =============\nname:\n%@\nreason:\n%@\ ncallstacksymbols:\n%@ ",
Name,reason,[arr componentsjoinedbystring:@ "\ n"];
NSString *path = [Applicationdocumentsdirectory () stringbyappendingpathcomponent:@ "Exception.txt"];
[url Writetofile:path atomically:yes encoding:nsutf8stringencoding error:nil];
In addition to having the option to write to a file under the app, the information is sent to the server through subsequent processing
You can also choose to call the program that sent the message, send the message to the specified e-mail address
Or call a handler to process this information
}

@implementation Nduncaughtexceptionhandler

-(NSString *) applicationdocumentsdirectory {
return [Nssearchpathfordirectoriesindomains (NSDocumentDirectory, Nsuserdomainmask, YES) lastobject];
}

+ (void) Setdefaulthandler
{
Nssetuncaughtexceptionhandler (&uncaughtexceptionhandler);
}

+ (nsuncaughtexceptionhandler*) gethandler
{
return Nsgetuncaughtexceptionhandler ();
}

@end

Exception Crash report:
============= Exception crash report =============
Name
Nsrangeexception
Reason
-[nsarray Objectatindex:]: Index 1 beyond bounds [0.. 0]
Callstacksymbols:
0 corefoundation 0x02393919 __exceptionpreprocess + 185
1 LIBOBJC. A.dylib 0x024e15de Objc_exception_throw + 47
2 corefoundation 0x0238958c-[__nsarrayi objectatindex:] + 236
3 Uncaughte 0x000022e8-[uncaughteappdelegate application:didfinishlaunchingwithoptions:] + 157
4 UIKit 0x002b8543-[uiapplication _callinitializationdelegatesforurl:payload:suspended:] + 1163
5 UIKit 0x002ba9a1-[uiapplication _runwithurl:payload:launchorientation:statusbarstyle:statusbarhidden:] + 346
6 UIKit 0x002c4452-[uiapplication handleevent:withnewevent:] + 1958
7 UIKit 0x002bd074-[uiapplication sendevent:] + 71
8 UIKit 0x002c1ac4 _uiapplicationhandleevent + 7495
9 graphicsservices 0x02bf9afa Purpleeventcallback + 1578
Ten corefoundation 0x02374dc4 __cfrunloop_is_calling_out_to_a_source1_perform_function__ + 52
Corefoundation 0x022d5737 __cfrunloopdosource1 + 215
Corefoundation 0x022d29c3 __cfrunlooprun + 979
Corefoundation 0x022d2280 cfrunlooprunspecific + 208
Corefoundation 0X022D21A1 Cfrunloopruninmode + 97
UIKit 0x002ba226-[uiapplication _run] + 625
UIKit 0x002c5b58 Uiapplicationmain + 1160
Uncaughte 0x00002228 main + 102
Uncaughte 0x000021b9 start + 53

The disadvantage is that not all program crashes are due to the occurrence of the exception can be caught, and sometimes cause a crash most of the reasons such as: Memory access errors, repeated release and other errors can not do, because this error it throws is signal, so must be dedicated to do signal processing. First define a Uncaughtexceptionhandler class, the code for the. h header file is as follows:


The code for the Uncaughtexceptionhandler class,. h header file is as follows:

1
2
3
4
5
6
#import

@interface uncaughtexceptionhandler:nsobject{
BOOL dismissed;
}
@end
1
void Installuncaughtexceptionhandler ();
then implement Installuncaughtexceptionhandler () in the. mm file, as follows:
void Installuncaughtexceptionhandler () {
Signal (SIGABRT, Mysignalhandler);
Signal (Sigill, Mysignalhandler);
Signal (SIGSEGV, Mysignalhandler);
Signal (SIGFPE, Mysignalhandler);
Signal (Sigbus, Mysignalhandler);
Signal (Sigpipe, Mysignalhandler);
}
Thus, when an application error occurs, the above signal will be entered into our custom callback function Mysignalhandler. In order to get the scene information in the crash, you can also add some code to get calltrace and device information, the complete code of the. mm file is as follows:

#import "UncaughtExceptionHandler.h"
#include #include

NSString * Const UNCAUGHTEXCEPTIONHANDLERSIGNALEXCEPTIONNAME = @ "Uncaughtexceptionhandlersignalexceptionname";

NSString * Const UNCAUGHTEXCEPTIONHANDLERSIGNALKEY = @ "Uncaughtexceptionhandlersignalkey";

NSString * Const UNCAUGHTEXCEPTIONHANDLERADDRESSESKEY = @ "Uncaughtexceptionhandleraddresseskey";

Volatile int32_t uncaughtexceptioncount = 0;

Const int32_t Uncaughtexceptionmaximum = 10;

Const Nsinteger Uncaughtexceptionhandlerskipaddresscount = 4;

Const Nsinteger Uncaughtexceptionhandlerreportaddresscount = 5;

@implementation Uncaughtexceptionhandler

+ (Nsarray *) backtrace

{

void* callstack[128];

int frames = BackTrace (callstack, 128);

Char **strs = Backtrace_symbols (callstack, frames);

int i;

Nsmutablearray *backtrace = [Nsmutablearray arraywithcapacity:frames];

for (

i = Uncaughtexceptionhandlerskipaddresscount;

I < Uncaughtexceptionhandlerskipaddresscount +

Uncaughtexceptionhandlerreportaddresscount;

i++)

{

[BackTrace addobject:[nsstring Stringwithutf8string:strs[i]];

}

Free (STRs);

return backtrace;

}

-(void) Alertview: (Uialertview *) Analertview Clickedbuttonatindex: (Nsinteger) Anindex

{

if (Anindex = = 0)

{

dismissed = YES;

}

}

-(void) HandleException: (NSException *) exception

{

Uialertview *alert =

[[[Uialertview Alloc]

Initwithtitle:nslocalizedstring (@ "Unhandled exception", nil)

Message:[nsstring stringwithformat:nslocalizedstring (

@ "can try to continue but the application is unstable.\n"

@ "%@\n%@", nil),

[Exception reason],

[[Exception UserInfo] Objectforkey:uncaughtexceptionhandleraddresseskey]

Delegate:self

Cancelbuttontitle:nslocalizedstring (@ "Quit", nil)

Otherbuttontitles:nslocalizedstring (@ "Continue", nil), nil]

Autorelease];

[Alert show];

Cfrunloopref Runloop = Cfrunloopgetcurrent ();

Cfarrayref allmodes = Cfrunloopcopyallmodes (Runloop);

while (!dismissed)

{

For (NSString *mode in (Nsarray *) allmodes)

{

Cfrunloopruninmode ((cfstringref) mode, 0.001, false);

}

}

Cfrelease (Allmodes);

Nssetuncaughtexceptionhandler (NULL);

Signal (SIGABRT, SIG_DFL);

Signal (Sigill, SIG_DFL);

Signal (SIGSEGV, SIG_DFL);

Signal (SIGFPE, SIG_DFL);

Signal (Sigbus, SIG_DFL);

Signal (Sigpipe, SIG_DFL);

if ([[[Exception name] isequal:uncaughtexceptionhandlersignalexceptionname])

{
<span style= "White-space:pre" ></span>kill (Getpid (), [[[Exception UserInfo] Objectforkey: Uncaughtexceptionhandlersignalkey] intvalue]);
}
Else
{
[Exception raise];
}
}
@end

nsstring* Getappinfo () {NSString *appinfo = [NSString stringwithformat:@ ' App:%@%@ (%@) \ndevice:%@\nos Version:%@%@ \nudid:%@\n ", [[NSBundle Mainbundle] objectforinfodictionarykey:@" Cfbundledisplayname "], [[NSBundle MainBundle] objectforinfodictionarykey:@ "Cfbundleshortversionstring"], [[NSBundle Mainbundle] objectforinfodictionarykey:@ " Cfbundleversion "], [Uidevice Currentdevice].model, [Uidevice currentdevice].systemname, [UIDevice CurrentDevice]. Systemversion, [Uidevice currentdevice].uniqueidentifier]; NSLog (@ "Crash!!!!%@", appInfo); return appInfo; } void Mysignalhandler (int signal) {int32_t Exceptioncount = OSAtomicIncrement32 (&uncaughtexceptioncount); Exceptioncount > Uncaughtexceptionmaximum)
{
Return
}

Nsmutabledictionary *userinfo =

[Nsmutabledictionary

Dictionarywithobject:[nsnumber Numberwithint:signal]

Forkey:uncaughtexceptionhandlersignalkey];

Nsarray *callstack = [Uncaughtexceptionhandler backtrace];

[UserInfo

Setobject:callstack

Forkey:uncaughtexceptionhandleraddresseskey];

[[[[Uncaughtexceptionhandler alloc] init] autorelease]

Performselectoronmainthread: @selector (handleexception:)

Withobject:

[NSException

Exceptionwithname:uncaughtexceptionhandlersignalexceptionname

Reason

[NSString stringWithFormat:

Nslocalizedstring (@ "Signal%d was raised.\n"

@ "%@", nil),

Signal, Getappinfo ()]

UserInfo:

[Nsdictionary

Dictionarywithobject:[nsnumber Numberwithint:signal]

Forkey:uncaughtexceptionhandlersignalkey]]

Waituntildone:yes];

}

void Installuncaughtexceptionhandler ()

{

Signal (SIGABRT, Mysignalhandler);

Signal (Sigill, Mysignalhandler);

Signal (SIGSEGV, Mysignalhandler);

Signal (SIGFPE, Mysignalhandler);

Signal (Sigbus, Mysignalhandler);

Signal (Sigpipe, Mysignalhandler);

}
Before applying your own didfinishlaunchingwithoptions, add a function:

-(void) Installuncaughtexceptionhandler
{
Installuncaughtexceptionhandler ();
}
Finally, add this line of code to the Didfinishlaunchingwithoptions:

1
[Self installuncaughtexceptionhandler];
Now, basically all crashes can hold. The following dialog box will appear when the crash occurs:

This allows you to easily pop up a dialog box when it crashes, and users will not feel so uncomfortable about the flash. You can then send the crash file to the mailbox by mail the next time you start, which depends on the needs of each application.

One of iOS apps-exception handling (Uncaughtexceptionhandler)

Related Article

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.