ios 搜集崩溃信息上传服务器,iOS 收集APP崩溃

UncaughtExceptionHandler

收集APP崩溃信息,上传到服务器,用于分析统计.

一些特殊场景,集成了某个第三方库,但不想它收集我们APP的崩溃信息.

收集APP崩溃信息

//苹果提供异常捕获相关函数

/** 获取异常捕获句柄

A pointer to the top-level error-handling function where you can perform last-minute logging before the program terminates.

*/

NSUncaughtExceptionHandler * _Nullable NSGetUncaughtExceptionHandler(void);

/** 设置异常捕获句柄

Changes the top-level error handler.

Sets the top-level error-handling function where you can perform last-minute logging before the program terminates.

*/

void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler * _Nullable);

) 处理流程

设置异常捕获句柄-->处理异常句柄回调-->收集崩溃信息-->存入本地文件系统-->

等待下次启动-->收集本地崩溃文件列表-->上传服务器-->清空本地崩溃文件列表

) 异常处理代码块

//处理signal报错

void ueh_SignalHandler(int signal) {

NSString* description = nil;

switch (signal) {

case SIGABRT:

description = [NSString stringWithFormat:@"Signal SIGABRT was raised!\n"];

break;

case SIGILL:

description = [NSString stringWithFormat:@"Signal SIGILL was raised!\n"];

break;

case SIGSEGV:

description = [NSString stringWithFormat:@"Signal SIGSEGV was raised!\n"];

break;

case SIGFPE:

description = [NSString stringWithFormat:@"Signal SIGFPE was raised!\n"];

break;

case SIGBUS:

description = [NSString stringWithFormat:@"Signal SIGBUS was raised!\n"];

break;

case SIGPIPE:

description = [NSString stringWithFormat:@"Signal SIGPIPE was raised!\n"];

break;

default:

description = [NSString stringWithFormat:@"Signal %d was raised!",signal];

}

NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];

NSArray *callStack = [UncaughtExceptionHandler backtrace];

[userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];

[userInfo setObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey];

}

void ueh_HandleException(NSException *exception) {

//获取调用堆栈

NSArray *callStack = [exception callStackSymbols];

NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];

[userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];

//在主线程中,执行制定的方法, withObject是执行方法传入的参数

[[[UncaughtExceptionHandler alloc] init]

performSelectorOnMainThread:@selector(handleException:)

withObject:

[NSException exceptionWithName:[exception name]

reason:[exception reason]

userInfo:userInfo]

waitUntilDone:YES];

}

// 异常处理入口

- (void)handleException:(NSException *)exception {

//存储日志

[[self class] saveDataWithException:exception];

//将错误日志传递给其它监听者.

if (_previousHandler) {

_previousHandler(exception);

}

}

拒绝第三方库收集崩溃

) 正常情况下,如果想要拒绝第三方库的收集,只需要在初使化第三方库后,设置

NSSetUncaughtExceptionHandler(ueh_HandleException);

//在处理 ueh_HandleException() 时,不传递异常事件即可。

) 特别情况处理

第三方初使化时,由于未知原因并不会马上调用NSSetUncaughtExceptionHandler(),

而我们在APP内调用NSSetUncaughtExceptionHandler()后,第三方可能在这之后才会调用此方法,即第三方在我们注册之后才注册了他们自己的监听回调函数,因此我们无法控制他们的行为.

Objective-C 作为基于 Runtime的语言,它有非常强大的动态特性,可以在运行期间自省、进行方法调剂、为类增加属性、修改消息转发链路,在代码运行期间通过 Runtime 几乎可以修改 Objecitve-C 层的一切类、方法以及属性。

对于runtime提供的API,我们只能操作NS体系的方法或函数 ,并不能去hook C的API函数。针对此情况,facebook开源三方框架fishhook,其主要作用就是动态修改 C 语言函数实现。其详细介绍可进github查询,现在我们来实现拒绝第三方库收集异常的业务.

实现的方式很简单:

0x01 注册我们自己的异常句柄函数

0x02 获取NSSetUncaughtExceptionHandler的函数地址.

0x03 声明属于我们自己的ext_NSSetUncaughtExceptionHandler函数.

0x04 使用rebind_symbols()方法,交换两个方法.

0x05 完成,如何额外处理某些三方库捕获异常,可在自定义的函数进行相关的处理操作即可.

++代码示例:++

/**

交互捕获异常函数声明

*/

static void ext_NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler * handler);

///

/**

捕获异常函数地址声明

*/

static void (*original_NSSetUncaughtExceptionHandler)(NSUncaughtExceptionHandler* __nullable handler);

void installUncaughtException() {

// 获取函数地址,并保存起来,用来进行交换.

original_NSSetUncaughtExceptionHandler = dlsym(RTLD_DEFAULT, "NSSetUncaughtExceptionHandler");

// 初始化一个 rebinding 结构体

struct rebinding open_rebinding =

{

"NSSetUncaughtExceptionHandler",

ext_NSSetUncaughtExceptionHandler,

(void *)& original_NSSetUncaughtExceptionHandler

};

// 将结构体包装成数组,并传入数组的大小,对原符号 open_rebinding 进行重绑定

rebind_symbols((struct rebinding[1]){open_rebinding}, 1);

}

void ext_NSSetUncaughtExceptionHandler() {

//对第三方库想监听异常信号的处理.

//...

}

1.随着苹果对ARC优化的越来越好,一般情况下不会出现崩溃异常(数组越界频率是最高的也最易排查. KVO问题是最难定位的)。但要出现了异常,经验不足的iOS开发人员很难定位到代码问题.

2.如果项目是基于Swift开发,线上版本如出现了异常也更难去定位具体的代码块,因为捕获堆栈内容,我们看到的并不是swift内的函数名,而是apple给我们混淆后的函数名,比较难去定位.但根据关键字函数名,还是可以定位到问题,这就需要iOS开发人员具有深厚的经验和能力了.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/527211.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python编程第八讲答案_小甲鱼Python第八讲课后习题

i 0string ‘ILoveFishC.com‘while i print(i)i 1答&#xff1a;i 0string ‘ILoveFishC.com‘length len(string)while i< length:print(i)i 1动手&#xff1a;0.设计一个验证用户密码程序&#xff0c;用户只有三次机会输入错误&#xff0c;不过如果用户输入的内容中包…

电脑摄像头未能创建连接服务器,Win7中摄像头提示未能创建视频预览错误怎么办...

最近有不少用户在我们网站上提问说他们在打开摄像头的时候&#xff0c;就会遇到打开摄像头的时候提示“未能创建视频预览&#xff0c;请检查设备连接”的问题&#xff0c;这是怎么回事呢&#xff0c;出现这样的原因的话有可能是电脑中毒了或者某些相关的服务没有启动导致的&…

华硕服务器主板型号命名规则,常见主板命名规则

最近因为想要组装 NAS&#xff0c;所以简单的了解了一下主板的命名规则。这里将总结一下。多数厂家遵循一般的规律&#xff1a;处理器类型芯片组芯片类型基本后缀芯片组名字由芯片厂商决定&#xff0c;AMD 在发布锐龙后抢了英特尔的命名方式&#xff0c;从低到高端 A320, B350,…

Ubuntu 常用命令之 date 命令用法介绍

&#x1f4d1;Linux/Ubuntu 常用命令归类整理 date命令在Ubuntu系统中用于显示或设置系统的日期和时间。 date常见的参数 -d, --dateSTRING&#xff1a;显示STRING指定的时间&#xff0c;而不是当前时间。-u, --utc, --universal&#xff1a;显示或设置协调世界时间。-R, --…

局部配置和全局配置_06. 教你零基础搭建小程序(解读全局配置文件-tabBar字段)...

自从开始在知乎上发教程后&#xff0c;发现一个事情啊&#xff0c;大家对于我写的教程&#xff0c;都在偷偷地收藏~~但是&#xff0c;却没有银点赞~知乎这个平台吧&#xff0c;点赞的分量比收藏更大&#xff0c;这里也不是要赞&#xff08;我知道自己还能做的更好&#xff09;&…

python编程类型_Python 基础编程 数据类型(一)

Python 对象类型对象类型类型的类名描述Characterchr单字节字符&#xff0c;在字符串中使用Integerint32位整数Floatfloat双精度(64位)浮点数Long integerlong任意大的整数Complexcomplex复数Character stringstr有序(数组)字符集Dictionarydict键 / 值 对字典Tupletuple不可变…

mac系统在云服务器地址,mac如何登陆云服务器地址

mac如何登陆云服务器地址 内容精选换一换本章节指导用户获取云服务器的IP地址等网卡信息。进入弹性云服务器页面。进入云服务器详情页面。进入网卡详情页面。网卡详情页面进入虚拟IP详情页&#xff0c;即可根据云服务器网卡信息找到绑定的虚拟IP地址。本章节介绍如何使用弹性云…

时间转化_Excel常见时间日期函数全讲解,10个函数教你如何进行日期转化

在工作中我们经常会碰到一些需要转化或者计算时间日期的工作&#xff0c;这里就需要我们用到一些常见的Excel时间日期函数。今天我们就通过十个案例来教大家&#xff0c;如何在实际工作中对时间日期进行转化处理。函数一、显示当前日期函数TODAY()2018/10/10函数二、显示当前日…

线扫相机 编码器_面阵和线扫工业相机选型

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。本文链接&#xff1a;https://blog.csdn.net/snowbird13/article/details/64919984一. 面阵相机和镜头选型已知&#xff1a;被检测物体大小为A*B,要…

hdc mfc 画扇形图_MFC画图总结-DIB图形绘制

http://blog.sina.com.cn/s/blog_4c75bd8c0100zsw7.html绘制DIB图到到设备&#xff0c;明白一点。DIB设备无关图形向设备CDC上绘的话&#xff0c;肯定是须要经过图形pixel像素转换的&#xff0c;要转换成设备的颜色像素格式。參考这段说明:DIB的颜色信息储存在自己的颜色表中。…

alive的不生效 keep vue_webpack打包vue项目 keep-alive不生效

项目会使用tab功能&#xff0c;进而需要对页面数据进行缓存。在本地开发的时候&#xff0c;能够正常缓存&#xff0c;但是在使用webpack打包后&#xff0c;上传至服务器发现缓存失效&#xff0c;导致有些业务出错。路由代码&#xff1a;module.exports (file: string) > { …

回旋滚动_中频炉电动旋转轴承,管道回旋轴承,电炉旋转轴承

中频炉电动旋转轴承&#xff0c;管道回旋轴承&#xff0c;电炉旋转轴承&#xff0c;&#xff0c;管道旋转轴承自带双边法兰,在集尘罩管道做法兰和主管道的法兰连接,旋转轴承可以360度旋转&#xff0c;除尘器管道轴承可以同时承受较大的轴向、径向负荷和倾覆力矩。除尘器旋转轴承…

dao层如何调用对象_你的项目应该如何正确分层?

你好&#xff0c;欢迎收听极客视点。 说起应用分层&#xff0c;大部分人都会认为这不是很简单嘛&#xff0c;就Controller、Service、Mapper三层。但在“简单”背后&#xff0c;很多人并没有将各层级的职责划分清楚。比如在很多代码中&#xff0c;Controller比Service还多&…

combobox 如何让text居中_MFC 中ListBox 与 ComboBox 中的文本如何实现水平居中与垂直居中 - 小众知识...

MFC 中&#xff0c; ListBox 与 ComboBox 中的项在设置了高度的情况下如何实现文本的水平居中与垂直居中&#xff1f;&#xff1f;&#xff1f;ListBox 与 ComboBox 中的数据均为动态添加文本内容含有数字、英文、中文void CMyComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemS…

android 子module混淆_Android 多模块打包混淆填坑记

最近有个 sdk 的项目使用了多模块(Module)开发&#xff0c;然后提供 jar 包给接入者使用&#xff0c;要求大部分类是混淆过的&#xff0c;保留几个接口&#xff0c;Android Studio 能够导出 aar 文件&#xff0c;对于导出 jar 却要大费一番周折。我在网上找到这个比较靠谱的解决…

mysql索引_MySQL索引介绍和实战

索引是什么MySQL官方对索引的定义为&#xff1a;索引(Index)是帮助MySQL高效获取数据的数据结构。可以得到索引的本质&#xff1a;索引是数据结构&#xff0c;索引的目的是提高查询效率&#xff0c;可以类比英语新华字典&#xff0c;根据目录定位词语如果没有目录呢&#xff0c…

mysql自增字段_MySQL自增字段的常用语句

学习MySQL数据库&#xff0c;MySQL自增字段是最基础的部分之一&#xff0c;下面为您介绍一些MySQL自增字段的常用语句&#xff0c;希望对您学习MySQL自增字段能些许帮助。1、创建表格时添加&#xff1a; create table table1(id int auto_increment primary key,...)2、创建表格…

mysql安装需要注意什么意思_mysql 安装过程及注意事项

1.1. 下载&#xff1a;我下载的是64位系统的zip包&#xff1a;下载zip的包&#xff1a;下载后解压&#xff1a;D:\软件安装包\mysql-5.7.20-winx641.2. 配置环境变量&#xff1a;变量名&#xff1a;MYSQL_HOME变量值&#xff1a;E:\mysql-5.7.20-winx64path里添加&#xff1a;%…

mysql 语句检查_mysql查询语句

一、简单查询1.最简单查询(查所有数据)select * from 表名 注意&#xff1a;* 代表所有列&#xff0c;并不是代表所有行例&#xff1a;select * from test2.查询指定列select 列名,列名 from 表名例&#xff1a;select code,name from test3.修改结果集的列名 asselect 列名 …

mysql索引 物理文件_MySQL体系结构之物理文件

一、MySQL日志文件mysql日志文件及功能&#xff1a;日志文件功能错误日志记录启动、停止、运行过程中mysqld时出现的问题通用日志记录建立客户端连接和执行的语句二进制日志记录更改数据的所有语句&#xff0c;还用于复制慢查询日志记录执行时间超过long_query_time秒的所有查询…