App崩溃是许多用户无法忍受的,较高的崩溃率会让用户失望,一般而言App崩溃无非以下几种原因:

  • 崩溃
  • CPU资源限制,CPU占用太高以及难以承受
  • 看门狗
  • 超过内存的界限
  • 后台任务超时
    崩溃

常见的崩溃来自于以下几个方面:

1,optional带来的崩溃,optional就像黑盒一样,在你打开之前你根本不知道里面有没有value,一旦发现值为空就会直接导致程序崩溃,所以面对后台返回的数据要做一种安全的处理机制:

do {     if let data = data,json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String: AnyObject] {             let id = json["id"] as? Int             let name = json["name"] as? String             print("found repo with id: \(id) name: \(name)")}} catch {     print("couldn't parse JSON") }

也许你会好奇,为什么要用do catch呢这是因为在NSJSONSerialization 类中,这是因为在jsonObjectWithData方法中使用了throws来标记,这告诉我们它或许会抛出异常,在swift是一门类型检查的语言,因此要求我们必须处理。一般使用optional绑定就可以安全处理了。

2,weak reference,使用过storyboard的童靴应该都会注意到对应的IBOutlet属性都是weak,很多人会问那为什么要用weak呢,其实官网都有很详细的描述:


Each time you ask the NSBundle or NSNib class to load a nib file, the underlying code creates a new copy of the objects in that file and returns them to you. (The nib-loading code does not recycle nib file objects from a previous load attempt.) You need to ensure that you maintain the new object graph as long as necessary, and disown it when you are finished with it. You typically need strong references to top-level objects to ensure that they are not deallocated; you don’t need strong references to objects lower down in the graph because they’re owned by their parents, and you should minimize the risk of creating strong reference cycles.

3,非法的操作 

4,断言和不能捕获的异常

当然收集崩溃的第三方很多,但是苹果本身也有自己的框架来收集崩溃日志的,苹果2018年推出了一个新的框架MetricKit.

ios中的jsonkit解析 ios解析json崩溃_App

用这个可以来收集崩溃日志最好不过,不过目前仅iOS13可用,例如最终栈的使用踪迹,异常代码,以及App终止的原因收集,为什么慎用第三方呢?时下是个大数据的时代,对于数据来说很重要,这就是为什么很多国外大公司基本上都是自己写框架,很少用别人的框架,代码都有漏洞,当然前期用户数据不大的情况下当然为了节省成本会这样做。

4,看门狗超时

超时操作一般都只是用在以下三个方法中:

application(_:didFinishLaunchingWithOptions:)    applicationDidEnterBackground(_:)    applicationDidEnterForeground(_:)

如果看门狗杀死了你的app,去看看有没有如下的情况:

  • 排除死锁情况的发生
  • 无线loop
  • 异步回调   

 减少动态库加载的时间,看门狗在模拟器上是失效的,当你App启动时间很长的时候看门狗可能会杀死你的App,所以优化势必是很重要的。

在第一个方法中我们往往会做如下的事情:

一般启动分为第一次启动,第一次启动主要会做如下的事情:

  • 加载Application defaults例如 NSUserDefaults,bundle配置等等
  • 检查private、beta发布
  • 初始化App标识符包括但不仅仅限于IDFV对于匿名用户
  • 初始化崩溃报告系统
  • 安装A/B 测试
  • 安装分析
  • 使用GCD或者OperationQueue来配置网络
  • 配置UI基础设施,例如导航栏,主题初始化UI等
  • 展示登录
  • 配置内存缓存 例如图片缓存等

这些任务可以很快加起来但是会减慢App启动时间,为了有效提升你需要住如下的工作:

  1. 标识哪些是在UI展示之前必须做的,如果你的App是第一次启动,没有必要去加载任何用户偏好设置,例如主题,缓存大小,刷新的间隔等,但是崩溃报告系统必须在第一次启动时候初始化
  2. 任务的顺序
  3. 切割任务到2个分类,一个是必须在主线程去做的,另外一个是在其他线程执行的。

4,其他任务要么在UI被加载之后执行要么异步执行,延迟去加载其他子系统,例如logger,analytic

热启动:App已经在内存中,挂在后台中,再次点击app图标进入App。

一般热启动就2个场景:

1,用户点击了图标

2,用户接收了一个deep link

很多时间我们都说App启动太慢了,主要是说冷启动-从零启动App。

一般的启动优化在此不做多说了。

异常代码导致的崩溃:

ios中的jsonkit解析 ios解析json崩溃_ios中的jsonkit解析_02

App被终止:

1,内存相关的终止:一般称之为零碎杂物,这是最为普遍的后台任务终止情况之一,如果发生了这样的情况,你不必要做任何事。它仅仅是系统需要释放内存给前台应用和其他运行的应用,例如音乐类的和导航类的,如果前台应用增长过快,你的app将被终止。

当进入后台时候你可以通过压缩你的内存直接减少终止的概率,当进入后台的时候,目标是少于50个字节,当然越小,越好。

考虑如下情况,一般删除缓存和资源,从磁盘读回,把这些事情放回到前台去再次做,你将引起其他app有可能终止,尽可能最小化前台的使用率。当然少于50个字节也不能完全保证不会发生。它的发生以秒来计算-后台化你的应用如果下一个用户行为要求大量的内存的话,例如启动相机,暴裂式的拍了大量图片。

那么我们该如何做呢?其实能做的就是进入后台的时候保存你的state,以至于当你的app下次启动时候,它能返回到用户上次操作的地方。使用UIKit内建的State restoration API就可以完成。

另外一个终止最普遍的情况就是后台任务超时。当从前台到后台时,你能得到一些额外的运行时去完成紧急的任务,调用 UIApplication.beginBackgroundTask.当你完成那个工作,调用 endBackgroundTask,如果你没有明确调用endBackgroundTask,当时间用完,系统将会被终止。终止发生在你暂停你的App后的30秒。

x8b0