行程介绍
行程日期
前序部队:2021/04/28 - 2021/05/09
集合部队:2021/05/01 - 2021/05/09
行程路线
西宁->张掖->敦煌->鸣沙山->苏干湖->茫崖翡翠湖->西台吉乃尔湖->水上雅丹->东台吉乃尔湖->大柴旦翡翠湖->茶卡盐湖->青海湖->西宁
行程亮点
翡翠湖、雅丹地貌、大戈壁、青海湖、敦煌、美食
前段时间通过搭建 Crash 平台的机会,知道了如何进行 Crash 的解析和聚类。那么如何去理解一个 Crash 呢?这篇文章是通过 WWDC 中的资料进行整理学习的。
崩溃当你的 app 试图做一些不被允许的事情导致被突然终止。如:
前期调研准备可参考上一篇系列文章:https://www.xuyanlan.com/2019/02/20/iOS-crash-report/
客户端收集 Crash 使用的是 PLCrashReporter 这个开源的库,集成方法有很多成熟的文章可以参考,这里不再赘述。而且有需要的话你可以在 signal_handler_callback
方法中获取到崩溃信息然后追加崩溃瞬间的一些 App 信息,对于定位 Crash 有着重要的作用。
实践中 Crash 解析方式并未用到上一篇文章中提到的自己实现的 macho 解析工具,但是前期的准备工作让后期搭建工作更加顺利。如果你的服务器不是 MacOS (是的话可以直接是使用 symbolicatecrash,只需要收集各个版本的固件即可)。我们所部署的 Crash 解析服务器是Linux。
发现了一个成熟的 Crash 解析工具 - llvm, 我所使用的版本是llvm8.0,部署非常简单,下载解压后就能使用。http://llvm.org/docs/CommandGuide/ 中列出了一些 Commands。 其中主要使用到的是:
llvm-symbolizer 用于定位代码位置,这个是解析 Crash 的重点,来看一个例子:
1 | llvm-symbolizer --obj=XXX:arm64 0x100301A5C 0x1003014DC 0x1002FDE74 0x1002FDD3C 0x1002FBE60 0x100188B10 |
深入理解 runloop
本文参考了多位前辈的文章、视频和源码进行学习、以及总结加深理解。
一般来讲,一个线程一次只执行一个任务,任务执行完成后线程就退出了,runloop 就是能让线程保持随时能处理任务但不退出的一个机制。这种机制就是 Event Loop 模型,实现这种模型的关键点在于:如何管理事件/消息,如何让线程在没有处理消息时休眠以避免资源占用、在有消息到来时立刻被唤醒。
OSX/iOS 系统中,提供了两个这样的对象:NSRunLoop 和 CFRunLoopRef。
CFRunLoopRef 是在 CoreFoundation 框架内的,它提供了纯 C 函数的 API,所有这些 API 都是线程安全的。
NSRunLoop 是基于 CFRunLoopRef 的封装,提供了面向对象的 API,但是这些 API 不是线程安全的。
RunLoop 实际上就是一个对象,这个对象管理了其需要处理的事件和消息,并提供了一个入口函数来执行上面 Event Loop 的逻辑。线程执行了这个函数后,就会一直处于这个函数内部 “接受消息->等待->处理” 的循环中,直到这个循环结束(比如传入 quit 的消息),函数返回。这种说法比较抽象,下面会结合开发过程中使用到的例子来配合源码进行理解。
【译】A taste of MVVM and Reactive paradigm
Medium 原文 A taste of MVVM and Reactive paradigm
原文博客 A taste of MVVM and Reactive paradigm
我喜欢 Swift,就像许多其他面向对象的编程语言一样。 Swift 允许你表示具有某些特点和执行一些操作的真实世界对象。
我倾向于认为 App 是一个每个对象都是一个人的世界。他们工作和沟通。如果一个人不能独自完成工作,他需要寻求帮助。举一个项目,例如,如果经理必须自己完成所有的工作,他会发疯的。因此需要组织和委派任务,并且需要许多人在项目上进行协作:设计师,测试人员,Scrum 主管,开发人员。任务完成后,需要通知经理。
这可能不是一个好例子。但至少你了解 OOP 中沟通和授权的重要性。当我开始 iOS 编程时,我对“架构”一词非常感兴趣。但在做了一段时间后,这一切都归结为识别和分担责任。本文讲述了 MVC 和 MVVM 的简单 Extract 类重构,以及如何进一步研究 Rx。您可以自由地创建自己的架构,但无论您做什么,一致性都是关键,不要让您的队友感到困惑或惊讶。
看看你最熟悉的架构 - MVC,模型视图控制器的简称。 在新建一个 iOS 项目时总是会得到一个这样的架构。 View 是您使用 UIView
,UIButton
,UILabel
呈现数据的位置。 Model 只是数据的一个设想的词。 它可以是您的实体,来自网络的数据,来自数据库的对象或来自缓存。Controller 是在 Model 和 View 间进行调解的东西。
ViewController
的问题在于它往往是巨大的。 Apple 把它作为宇宙的中心,它拥有许多属性和责任。你可以用 UIViewController
做很多事情。诸如与故事板交互,管理视图,配置视图轮换,状态恢复等事情。 UIViewController
设计了很多可以覆盖和自定义的方法。
上一篇文章中提到了如何自建一个 Crash 平台,其中通过对系统库 (MachO) 的结构解析来寻找崩溃符号。这篇文章就具体讲讲 MachO 文件的结构分析。
iOS中,我们平时看见的 MachO 文件你肯定不陌生,包括静态库(.a)、dSym (yourAppName.dSym)、系统动态库 (/usr/lib/libobjc.A.dylib)、可执行文件等。具体类型下面会讲到。
MachO 二进制文件可以根据前四字节的magic_num来判断是不是 Fat (包含一个或多个架构,有 Fat_Header), 每个架构同样是的 MachO文件。可以这样比喻,相当于对一个或多个文件用文件夹压缩了下。zip 包相当于 Fat,文件是 Thin。每个文件的内部结构式一致的。
可以看到 Fat 多了 Fat_Header信息, 信息中包含架构数,每个架构的基本信息。
Fat 可以通过lipo -thin 命令分解出 thin。 thin 也可以合并成 Fat。
1 | //分解 |
【译】Symbolicating an iOS Crash Report
通常,当您收到来自iTunes连接的崩溃报告或提供移动崩溃收集和报告的第三方服务(如Apteligent)时,该服务将负责为您提供符号化后的崩溃。如果你没有上传符号,你可能会发现自己有一个非符号化的崩溃,没有别的东西可以继续。这样的崩溃文件对于调试可能影响大量用户的问题并不是非常有用。
在这种情况下,您必须通过将回溯堆栈地址解析为符号来对崩溃报告进行符号化,以获取有关崩溃的有用信息。
幸运的是,完全有可能手动符号化崩溃报告。本文将概述您需要的信息,向您展示如何解释崩溃报告,并查看OSX和XCode上可用的一些工具来符号化崩溃。
崩溃报告中只有两个部分与符号化异常跟踪相关。第一个是 Exception Backtrace 部分。这显示了崩溃时应用程序的调用堆栈。此特定崩溃日志片段显示了我们的 ApteligentExampleApp 应用程序内部崩溃的回溯。
1 | Last Exception Backtrace: |