摘要:本文将带你了解IOS开发入门iOS异常处理,希望本文对大家学IOS有所帮助。
本文将带你了解IOS开发入门iOS异常处理,希望本文对大家学IOS有所帮助。
开发iOS应用,解决Crash问题始终是一个难题。
Crash分为两种,
一种是由EXC_BAD_ACCESS引起的,原因是访问了不属于本进程的内存地址,有可能是访问已被释放的内存;
另一种是未被捕获的Objective-C异常(NSException),导致程序向自身发送了SIGABRT信号而崩溃。
其实对于未捕获的Objective-C异常,我们是有办法将它记录下来的,如果日志记录得当,能够解决绝大部分崩溃的问题。这里对于UI线程与后台线程分别说明
<h1 id="一-系统crash">一. 系统Crash
对于系统Crash而引起的程序异常退出,可以通过NSSetUncaughtExceptionHandler机制捕获,代码:
实现一个用于处理异常的方法
<code>void HandleException(NSException *exception)
{
// 异常的堆栈信息
NSArray *stackArray = [exception callStackSymbols];
// 出现异常的原因
NSString *reason = [exception reason];
// 异常名称
NSString *name = [exception name];
NSString *exceptionInfo = [NSString stringWithFormat:@"Exception reason:%@\nException name:%@\nException stack:%@",name, reason, stackArray];
NSLog(@"%@", exceptionInfo);
NSString *logPath=[NSString stringWithFormat:@"%@/Documents/error.log",NSHomeDirectory()];
[exceptionInfo writeToFile:logPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
</code>
然后在启动appdidFinishLaunchingWithOptions的时候设置
<code><code>NSSetUncaughtExceptionHandler (&UncaughtExceptionHandlers);//系统异常捕获</code></code>
当捕获到异常时,就会调用UncaughtExceptionHandlers来出来异常
二. 处理signal
使用Objective-C的异常处理是不能得到signal的,如果要处理它,我们还要利用unix标准的signal机制,注册SIGABRT, SIGBUS, SIGSEGV等信号发生时的处理函数。该函数中我们可以输出栈信息,版本信息等其他一切我们所想要的。
NSSetUncaughtExceptionHandler 用来做异常处理,但功能非常有限.而引起崩溃的大多数原因如:内存访问错误,重复释放等错误就无能为力了,因为这种错误它抛出的是Signal,所以必须要专门做Signal处理
代码如下:
首先定义并实现一个方法如:
<code><code>#include <execinfo.h>
//Signal处理方法
void MySignalHandler(int signal)
{
NSMutableString *mstr = [[NSMutableString alloc] init];
[mstr appendString:@"Stack:\n"];
void* callstack[128];
int i, frames = backtrace(callstack, 128);
char** strs = backtrace_symbols(callstack, frames);
for (i = 0; i <frames; atomically:yes="" documents="" encoding:nsutf8stringencoding="" exceptioninfo="" logpath="[NSString" mstr="" nsstring="" pre="" writetofile:logpath=""></frames;></execinfo.h></code></code>
在启动app的时候设置各种信号的回调处理
<code><code>//信号量截断
signal(SIGABRT, MySignalHandler);
signal(SIGILL, MySignalHandler);
signal(SIGSEGV, MySignalHandler);
signal(SIGFPE, MySignalHandler);
signal(SIGBUS, MySignalHandler);
signal(SIGPIPE, MySignalHandler);</code></code>
这样当接收到信号的时候,就会调用MySignalHandler方法
三. 实战
首先定义一个UncaughtExceptionHandler类,用来捕获处理所有的崩溃信息
<code><code><code>@interface UncaughtExceptionHandler : NSObject
{
BOOL dismissed;
}
+ (void)InstallUncaughtExceptionHandler;
@end</code></code></code>
<code><code><code>#import <uikit uikit.h="">
#import "UncaughtExceptionHandler.h"
#include <libkern osatomic.h="">
#include <execinfo.h>
NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName";
NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";
NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey";
NSString * const UncaughtExceptionHandlerFileKey = @"UncaughtExceptionHandlerFileKey";
volatile int32_t UncaughtExceptionCount = 0;
const int32_t UncaughtExceptionMaximum = 10;
const NSInteger UncaughtExceptionHandlerSkipAddressCount = 4;
const NSInteger UncaughtExceptionHandlerReportAddressCount = 5;
void MySignalHandler(int signal);
@implementation UncaughtExceptionHandler
+(void) InstallUncaughtExceptionHandler
{
NSSetUncaughtExceptionHandler (&UncaughtExceptionHandlers);////系统异常捕获(越界)
//信号量截断
signal(SIGABRT, MySignalHandler);
signal(SIGILL, MySignalHandler);
signal(SIGSEGV, MySignalHandler);
signal(SIGFPE, MySignalHandler);
signal(SIGBUS, MySignalHandler);
signal(SIGPIPE, MySignalHandler);
}
//获取函数堆栈信息
+ (NSArray *)backtrace
{
void* callstack[128];
int frames = backtrace(callstack, 128);//用于获取当前线程的函数调用堆栈,返回实际获取的指针个数
char **strs = backtrace_symbols(callstack, frames);//从backtrace函数获取的信息转化为一个字符串数组
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)saveCreash:(NSException *)exception file:(NSString *)file
{
NSArray *stackArray = [exception callStackSymbols];// 异常的堆栈信息
NSString *reason = [exception reason];// 出现异常的原因
NSString *name = [exception name];// 异常名称
//或者直接用代码,输入这个崩溃信息,以便在console中进一步分析错误原因
NSLog(@"CRASH: %@", exception);
NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
NSString * _libPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:file];
// NSString *_libPath=[NSHomeDirectory() stringByAppendingPathComponent:file];
&nbs
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之IOS频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号