[iOS]异常捕捉
UncaughtExceptionHandler.h
#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface UncaughtExceptionHandler : NSObject @end void UncaughtExceptionHandlerStart(void); NS_ASSUME_NONNULL_END
UncaughtExceptionHandler.m
#import "UncaughtExceptionHandler.h"
#import <UIKit/UIKit.h>
#import <libkern/OSAtomic.h>
#import <execinfo.h> NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName";
NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";
NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey"; volatile int32_t UncaughtExceptionCount = ;
const int32_t UncaughtExceptionMaximum = ; const NSInteger UncaughtExceptionHandlerSkipAddressCount = ;
const NSInteger UncaughtExceptionHandlerReportAddressCount = ; @interface UncaughtExceptionHandler ()
{
BOOL dismissed;
}
@end @implementation UncaughtExceptionHandler + (NSArray *)backtrace
{
void *callstack[];
int frames = backtrace(callstack, );
char **strs = backtrace_symbols(callstack, frames); NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
int end = UncaughtExceptionHandlerSkipAddressCount + UncaughtExceptionHandlerReportAddressCount; for (int i = UncaughtExceptionHandlerSkipAddressCount;i < end;i++)
{
[backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
}
free(strs); return backtrace;
} - (void)handleException:(NSException *)exception
{
NSString *reason = [exception reason];
NSString *addresses = [[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@""
message:[NSString stringWithFormat:@"reason:%@\n addresses:%@",reason,addresses]
delegate:self
cancelButtonTitle:@"退出"
otherButtonTitles:@"继续", nil];
[alert show]; CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop); while (!dismissed)
{
for (NSString *mode in (__bridge 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])
{
kill(getpid(), [[[exception userInfo] objectForKey:UncaughtExceptionHandlerSignalKey] intValue]);
}else{
[exception raise];
}
} - (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex
{
if (anIndex == )
{
dismissed = YES;
}
} @end void HandleException(NSException *exception);
void SignalHandler(int signal); void UncaughtExceptionHandlerStart(void)
{
NSSetUncaughtExceptionHandler(&HandleException);
signal(SIGABRT, SignalHandler);
signal(SIGILL, SignalHandler);
signal(SIGSEGV, SignalHandler);
signal(SIGFPE, SignalHandler);
signal(SIGBUS, SignalHandler);
signal(SIGPIPE, SignalHandler);
} void HandleException(NSException *exception)
{
int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount > UncaughtExceptionMaximum)
{
return;
} NSArray *callStack = [UncaughtExceptionHandler backtrace];
NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
[userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey]; [[[UncaughtExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:)
withObject:[NSException exceptionWithName:[exception name] reason:[exception reason] userInfo:userInfo]
waitUntilDone:YES];
} void SignalHandler(int signal)
{
int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount > UncaughtExceptionMaximum)
{
return;
} NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey]; NSArray *callStack = [UncaughtExceptionHandler backtrace];
[userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey]; [[[UncaughtExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:)
withObject:[NSException exceptionWithName:UncaughtExceptionHandlerSignalExceptionName
reason:[NSString stringWithFormat:@"Signal %d was raised.",signal]
userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:signal]
forKey:UncaughtExceptionHandlerSignalKey]]
waitUntilDone:YES];
}
开启异常捕捉
#import "AppDelegate.h"
#import "UncaughtExceptionHandler.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch. UncaughtExceptionHandlerStart(); return YES;
}
异常示例
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSArray *array = @[@""];
NSLog(@"%@",array[]);
}
运行效果

[iOS]异常捕捉的更多相关文章
- iOS异常捕获
文章目录 一. 系统Crash 二. 处理signal 下面是一些信号说明 关键点注意 三. 实战 四. Crash Callstack分析 – 进⼀一步分析 五. demo地址 六. 参考文献 前言 ...
- iOS异常采用处理方式
iOS开发过程中我们经常会遇到异常问题 对异常的处理一般采用打印或者直接抛出.这样可以很方便我们调试过程有所参考,而且方便我们查看异常产生的位置信息 NSError(错误信息) 采用NSError的情 ...
- 基础知识《十》java 异常捕捉 ( try catch finally ) 你真的掌握了吗?
本文转载自 java 异常捕捉 ( try catch finally ) 你真的掌握了吗? 前言:java 中的异常处理机制你真的理解了吗?掌握了吗?catch 体里遇到 return 是怎么处理 ...
- Java多线程——<七>多线程的异常捕捉
一.概述 为什么要单独讲多线程的异常捕捉呢?先看个例子: public class ThreadException implements Runnable{ @Override public void ...
- Oracle- 存储过程和异常捕捉
这段时间晚上有时候去打打球,回家看看电视剧,日子一天天过…….学了点ORACLE存储过程基础,作一下备注,以便日后需查阅. 创建无参存储过程 create procedure p_myPro1 is ...
- php错误及异常捕捉
原文:php错误及异常捕捉 在实际开发中,错误及异常捕捉仅仅靠try{}catch()是远远不够的. 所以引用以下几中函数. a) set_error_handler 一般用于捕捉 E_NOTI ...
- android中全局异常捕捉
android中全局异常捕捉 只要写代码就会有bug,但是我们要想办法收集到客户的bug.有第三方bugly或者友盟等可以收集.但是,android原生就提供了有关收集异常的api,所以我们来学习一下 ...
- Spring 全局异常捕捉
Spring全局异常捕捉类 注解@ControllerAdvice package com.sicdt.sicsign.web.bill.controller; import org.springfr ...
- 5.全局异常捕捉【从零开始学Spring Boot】
在一个项目中的异常我们我们都会统一进行处理的,那么如何进行统一进行处理呢? 新建一个类GlobalDefaultExceptionHandler, 在class注解上@ControllerAdvice ...
随机推荐
- JavaScript写九九乘法表
<script language=javascript> for(i=1;i<=9;i++){ for(j=1;j<=9;j++){ document.write (i+&qu ...
- 关于Datastage资料库的一点小发现
这里的资料库,指的是Datastage Metadata层,在Datastage7.5以后,需要在安装Datastage时安装一个数据库用于存放用户数据. 昨天领导要求安装Datastage集群/高可 ...
- 使用jvisualvm的jstatd方式远程监控Java程序
使用Java自带的jvisualvm调试Java程序,可以查看CPU.内存.类及线程等信息,还可以进行Dump,无疑是一个利器 由于客户端是Windows.服务端是Linux,并且是最小安装的Linu ...
- jsp到java后台中文乱码问题
---首先描述一下我的情况,我的jsp 设置了编码格式 <%@ page language="java" contentType="text/html; ch ...
- 在Linux上利用core dump和GDB调试
段错误(segfault) "段错误"是程序试图操作不允许访问或试图访问的不允许内存的情况.可能导致段错误的原因主要有: 1.试图解引用空指针(你不允许访问内存地址0) 2.试图解 ...
- zTree创建quickSearch检索框
<!--html元素----> <div id="plantTreeDiv" class="zTree-box treeZone"> & ...
- C# 数据上传(自用笔记)
#region 数据上传 [HttpPost] public ActionResult UploadFile() { HttpFileCollectionBase files = Request.Fi ...
- magento2 重置后台密码
项目根目录:运行如下命令 bin/magento admin:user:create --admin-user="admin" --admin-password="123 ...
- 面向对象程序设计_Task5_Calculator1.5.0
The 3rd part of the Calculator program _ FILE I/O 题目链接:第五次作业(计算器第三步) github链接:Calculator_1.5.0 第五次作业 ...
- 第2次作业——APP的案例分析
APP的案例分析 网易有道词典APP,使用这个软件有三年之久.唯独最爱的一点就是我每天都能听到不一样的英文歌看到创作歌手的来历,当然偶尔也会有其他国家的歌.起初使用这个软件的目的是用来查单词,每天积累 ...