干货 | 携程火车票iOS项目开发体验优化实践

2022-09-13 13:13:47 浏览数 (1)

作者简介

东海 ,携程移动开发专家,专注于移动端框架、移动端性能。

元帅,携程资深软件工程师,致力于平台基建开发。

一、背景

现在各大公司的APP都采用的是组件化架构,组件化架构带来了高内聚、低耦合、平台化等诸多有点,使工程结构更加清晰,工程管理更加轻松。iOS工程大多采用CocoaPod进行组件化管理,一些大型的项目需要打包平台来执行组件打bundle包和APP打测试包的任务,在开发方面会采用二进制与源码切换的方式来提高编译速度。

组件化虽然对APP项目的工程管理带来了巨大的好处,但是对开发人员来讲,存在着一些繁琐的问题:

  • 在开发中,如果需要调试未解开源码的组件,就需要重新执行命令解开相应组件的源码才能进行调试。
  • 每切换一次组件的源码,都需要在终端输入一串加了各种参数的命令来执行pod install,手动输入慢,而且容易出错。
  • 组件化使得组件颗粒度变得越来越细,每个人所管理的组件数量就会多,每次组件更新都需要在打包平台上进行打包,等组件bundle包打完,再打测试包进行验证。

这些虽然能让工作正常进行,但是繁琐重复的操作却影响了开发人员的开发效率。

二、现状

携程火车票APP一直以来采用的也是组件化管理,在去年改用CocoaPod进行组件化管理,随着业务的迭代和基础建设不断的完善,pod组件也越来越精细化,目前pod组件数量已超60 。

pod组件数量越庞大,开发人员维护的成本也会越高,不仅要管理维护每个pod组件的更新,还要处理pod组件打bundle包问题、测试包打包时间长的问题。上述繁琐、重复、耗时的操作困扰着我们的iOS开发人员。如果能尽可能的对这些开发体验问题进行优化,那么必然会带来开发人员效率的提升。

三、优化方案

为了让开发人员调试代码更加方便,打包测试体验更好,开发过程更加专注,我们做了许多方面的操作优化和技术实践,主要有:

3.1 通过技术手段,实现二进制调试

在开发过程,难免会遇到自己想调试的组件没有解开源码,程序在运行中崩溃但是崩溃在了未解开源码的组件上,自己看到的只是一堆不明所以的汇编代码(图1),无法像源码调试那样看到足够丰富的调试信息。

图1

3.1.1 二进制文件分析

如何才能不解开源码也能调试二进制、崩溃在了二进制组件上也能定位到具体哪一行成了我们新的问题。我们找了各种资料,找到了美团有款zsource的CocoaPod插件可以进行二进制调试,虽未开源,但大致逻辑文章里已经罗列的很清晰,大致原理:

以libXXXX.a二进制文件为例,用 MachOView 来查看二进制文件,以获取到更友好的二进制信息。我们可以看到 “debug_str” Section 这些信息都存在了二进制的中。debug_str在编译的时候内部会记录源码地址:

图2

使用命令在终端输入: 

dwarfdump ./libXXXX.a | grep 'XXXX'

注意到了 AT_name 这个字段名,去DWARF 1.1.0 Reference文档中查阅,我们可以得知:

  •  一个DW_AT_name属性,其值是一个以空字符结尾的字符串,其中包含从其派生编译单元的主源文件的完整或相对路径名。 
  • 一个DW_AT_comp_dir属性,其值是一个以空值结尾的字符串,其中包含编译命令的当前工作目录,该编译命令以某种形式将Forelax视为主机系统,从而生成此编译单元。

XXXX.swift源文件存在这个地址下: /Users/marshal/Desktop/XXXX/XXXX/XXXX.swift

这个地址就是编译时源码所在地址,Debug调试的时候,编译器会先从这里拿对应映射地址去加载源码文件。如果存在对应地址存在源码文件时,就能进入源码调试。

3.1.2 脚本开发

了解基础原理后,那接下来的事情就是解决各种问题障碍:

1)要获取到静态库的源码。

2)获取静态库中存储的编译静态库时源码文件所在的路径。

3)在本地创建上面

0 人点赞