「这是我参加2022初次更文应战的第4天,活动详情检查:2022初次更文应战」
描述
模拟器和真机调试运转正常,可是导出ipa包装置运转呈现奔溃。记载一下提示一下遇到相同问题的人少走弯路。
思路
首要遇到问题,头脑要保持清醒。考虑为什么会呈现这样的问题?
- 模拟器和真机调试运转正常,模拟器和真机调试是在
DeBug
形式下运转的 - 导出
ipa包
的环境是Release
形式下
所以能够重点是在Release形式下检查溃散信息才干定位问题。
检查ipa包溃散日志
手机数据线衔接电脑,凭借Xcode就能够看,Xcode
-> Window
-> Devices and Simulator
进入后,选择【View Device Logs】
检查日志信息
日志文件看的好难过,好像也没有办法定位具体问题,接着剖析
方才不是剖析在Release
形式下呈现的问题嘛,所以能够直接将本地调试的Dudeg
的形式修改为Relese
形式,然后运转。
默许是Debug
形式,选择Release
形式,然后本地调试的时分就和导出的ipa环境共同啦。
同时记得要勾选 【Zombie Ojects】,能够定位出野指针和僵尸目标。然后运转Xcode,能够定位到具体问题啦,同时控制台也输出了运用的目标提早释放导致的问题。
简略检查手机溃散信息几种办法
办法1:手机设置检查溃散日志
步骤:【设置】-> 【隐私】 -> 【剖析与改进】-> 【剖析数据】
办法2: Xocde东西
手机数据线衔接电脑,凭借Xcode就能够看,Xcode
-> Window
-> Devices and Simulator
,具体和上面共同,请参照上图示例。
办法3: 第三发软件Itools
经过数据线衔接 iOS 手机和电脑
办法四:控制台资源库
能够看到一切和该电脑同步过的设备的溃散日志(.crash文件)
输入下方的文件地址:
~/Library/Logs/CrashReporter/MobileDevice
找到自己手机设备的日志信息
开发程序进程也会呈现程序crash的状况,那么这时生成的文件目录为:
~/Library/Logs/DiagnosticReports/
线上溃散日志
线上监听crash的几种办法
办法1: 三方平台的SDK
例如:腾讯Bugly、crashlytics、友盟SDK
办法2: 自己完结反常监听,然后提交后台
自己完结反常监听的办法稍微复杂点,需求异步监听使命,不能影响到主进程的使命体验
常见的形成的溃散的状况
1.数组越界
在取数据索引时越界,App 会产生溃散。还有一种状况,便是给数组添加了 nil 会溃散
2.多线程问题
在子线程中进行 UI 更新可能会产生溃散。多个线程进行数据的读取操作,因为处理时机不共同,比方有一个线程在置空数据的同时另一个线程在读取这个数据,可能会呈现溃散状况。
3.主线程无呼应
假如主线程超过体系规则的时刻无呼应,就会被 Watchdog 杀掉。这时,溃散问题对应的反常编码是 0x8badf00d。
4.野指针
野指针指向一个已删去的目标拜访内存区域时,会呈现野指针溃散。野指针问题是需求咱们重点重视的,因为它是导致 App 溃散的最常见,也是最难定位的一种状况
信号可捕捉 | 信号不可捕捉 |
---|---|
KVO问题 | 后台使命超时 |
NSNotification线程问题 | 内存打爆 |
数组越界 | 主线程卡顿超阀值 |
野指针 | …. |
信号可捕获的溃散日志搜集
翻开 Xcode 的菜单选择 Product -> Archive
然后,在提交时选上“Upload your app’s symbols to receive symbolicated reports from Apple”,以后你就能够直接在 Xcode 的 Archive 里看到符号化后的溃散日志了。
可是这种检查日志的办法,每次都是纯手工的操作,并且时效性较差。所以,现在许多公司的溃散日志监控体系,都是经过PLCrashReporter这样的第三方开源库捕获溃散日志,然后上传到自己服务器上进行全体监控的。
而没有服务端开发能力,或许对数据不敏感的公司,则会直接运用Fabric或许Bugly来监控溃散。
信号捕获的原理
在溃散日志里,你经常会看到下面这段阐明:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
它表明的是,EXC_BAD_ACCESS
这个反常会经过 SIGSEGV
信号发现有问题的线程。虽然信号的种类有许多,可是都能够经过注册 signalHandler
来捕获到。
其完结代码,如下所示:
void registerSignalHandler(void) {
signal(SIGSEGV, handleSignalException);
signal(SIGFPE, handleSignalException);
signal(SIGBUS, handleSignalException);
signal(SIGPIPE, handleSignalException);
signal(SIGHUP, handleSignalException);
signal(SIGINT, handleSignalException);
signal(SIGQUIT, handleSignalException);
signal(SIGABRT, handleSignalException);
signal(SIGILL, handleSignalException);
}
void handleSignalException(int signal) {
NSMutableString *crashString = [[NSMutableString alloc]init];
void* callstack[128];
int i, frames = backtrace(callstack, 128);
char** traceChar = backtrace_symbols(callstack, frames);
for (i = 0; i <frames; ++i) {
[crashString appendFormat:@"%s\n", traceChar[i]];
}
NSLog(crashString);
}
上面这段代码对各种信号都进行了注册,捕获到反常信号后,在处理办法 handleSignalException
里经过 backtrace_symbols
办法就能获取到当前的仓库信息。仓库信息能够先保存在本地,下次启动时再上传到溃散监控服务器就能够了。
信号不可捕获的溃散日志搜集
App 退到后台后,即便代码逻辑没有问题也很容易呈现溃散。并且,这些溃散往往是因为体系强制杀掉了某些进程导致的,而体系强杀抛出的信号还因为体系限制无法被捕获到。
iOS 后台保活的 5 种办法
- Background Mode
- Background Fetch
- Silent Push
- PushKit
- Background Task (App 退后台后,默许都会运用这种办法)
收集进程原理
Background Task 这种办法,便是体系供给了beginBackgroundTaskWithExpirationHandler 办法来延长后台履行时刻,能够解决你退后台后还需求一些时刻去处理一些使命的诉求。
- (void)applicationDidEnterBackground:(UIApplication *)application {
self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^( void) {
//你的使命逻辑
[self yourTask];
}];
}
在这段代码中,yourTask 使命最多履行 3 分钟,3 分钟内 yourTask 运转完结,你的 App 就会挂起。 假如 yourTask 在 3 分钟之内没有履行完的话,体系会强制杀掉进程,从而形成溃散,这便是为什么 App 退后台容易呈现溃散的原因。
选用 Background Task 办法时,咱们能够依据 beginBackgroundTaskWithExpirationHandler 会让后台保活 3 分钟这个阈值,先设置一个计时器,在接近 3 分钟时判别后台程序是否还在履行。假如还在履行的话,咱们就能够判别该程序即将后台溃散,进行上报、记载,以达到监控的效果。
溃散日志剖析
咱们收集到的溃散日志,首要包含的信息为:进程信息、基本信息、反常信息、线程回溯。
- 进程信息:溃散进程的相关信息,比方溃散陈述仅有标识符、仅有键值、设备标识;
- 基本信息:溃散产生的日期、iOS 版别;
- 反常信息:反常类型、反常编码、反常的线程;
- 线程回溯:溃散时的办法调用栈。 一些被体系杀掉的状况,咱们能够经过反常编码来剖析。 常见的便是如下三种:
- 0x8badf00d,表明 App 在必定时刻内无呼应而被 watchdog 杀掉的状况。
- 0xdeadfa11,表明 App 被用户强制退出。
- 0xc00010ff,表明 App 因为运转形成设备温度太高而被杀掉。