IOS开发入门之异常处理
白羽 2018-11-23 来源 :网络 阅读 911 评论 0

摘要:本文将带你了解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频道!


本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程