Lyft iOS 应用扩展开发挑战:如何在有限资源下实现卓越用户体验
引言:
在移动互联网时代,应用扩展已成为提升用户体验、扩展应用功能的重要手段。然而,在看似简单的应用扩展背后,却隐藏着诸多技术挑战。近日,Lyft 工程师 ArturStepaniuk 和 Max Husar 在一篇技术文章中详细阐述了 Lyft 在为其 iOS 应用创建应用扩展时所面临的挑战,以及他们如何克服这些挑战,在有限的资源限制下,实现卓越的用户体验。他们的经验为其他开发者提供了宝贵的参考,也揭示了移动应用开发中一些不为人知的复杂性。
主体:
1. 应用扩展的价值与挑战
Lyft 作为一家知名的出行服务公司,其 iOS 应用集成了 Apple Maps 扩展,允许用户在 Apple Maps 应用内直接查看 Lyft 的优惠信息,这无疑为用户提供了极大的便利。然而,创建这样的应用扩展并非易事。
1.1. 资源限制:RAM 与二进制大小的博弈
苹果对 iOS 应用扩展的资源限制非常严格,其中最关键的限制在于 RAM 和二进制大小。
- RAM 限制: 应用扩展的可用 RAM 通常只有 20 到 50MB,具体取决于 iOS 版本、设备型号和其他因素。这意味着开发者必须非常谨慎地管理内存使用,避免出现内存溢出导致应用崩溃。
- 二进制大小限制: 应用扩展的二进制大小直接影响应用的下载和安装时间。过大的二进制大小不仅会延长用户等待时间,还可能触发额外的确认对话框,甚至导致安装失败。苹果对蜂窝数据下载的应用大小有严格限制,超过 200MB 的应用下载时会弹出额外的确认对话框,影响用户体验。
1.2. 动态链接的缺失:静态链接的无奈
在传统的应用开发中,动态链接可以有效地减少应用二进制大小,并提高代码重用率。然而,iOS 应用扩展并不支持动态链接。这意味着所有依赖项都必须静态链接到扩展中,这无疑会增加应用的二进制大小和内存占用。
2. Lyft 的解决方案:依赖关系分析与优化
面对上述挑战,Lyft 工程师采取了一系列策略,通过深入的依赖关系分析和优化,成功地减小了应用扩展的二进制大小和内存占用。
2.1. 依赖关系图分析:寻找性能瓶颈
Lyft 使用 Bazel 作为构建系统,这为他们提供了强大的依赖关系分析工具。他们利用 Bazel 的 query --output=graph
命令生成依赖关系图,并使用 Graphviz 可视化软件将其呈现出来。通过分析依赖关系图,Lyft 工程师可以清晰地了解哪些模块占用了最多的资源,并找出性能瓶颈。
2.2. 二进制大小测量:精确评估依赖项影响
为了精确测量每个模块对二进制大小的影响,Lyft 工程师将每个模块作为唯一的依赖项添加到Apple Maps 扩展中,并使用 binary-size-diff
工具进行分析。binary-size-diff
工具可以对比基础分支和给定拉取请求之间的二进制大小差异,从而精确评估删除或包含依赖项的实际效果。
2.3. 传递依赖关系分析:剥离不必要的依赖
在确定了占用大量资源的模块后,Lyft 工程师需要进一步分析这些模块的传递依赖关系,找出哪些依赖项是不必要的。他们使用 Bazel 的 bazel query 'allpaths(INITIAL_MODULE_PATH:INITIAL_MODULE_NAME, TARGET_MODULE_PATH:TARGET_MODULE_NAME)' --output=graph | grep -v 'node \\[shape=box\\];' \u003e relations.dot
命令,显示将所调查模块与其每个较大依赖项连接起来的路径中包含哪些模块。通过分析这些路径,他们可以删除或使目标模块不依赖这些不必要的依赖项。
2.4. 代码复制:创建最小依赖项
在某些情况下,Lyft 团队发现某些依赖项过于庞大,难以通过简单的依赖关系优化来解决。在这种情况下,他们决定复制一项服务,创建最小依赖项,以打破对较大模块的依赖。这种方法虽然增加了代码维护的成本,但却有效地减小了应用扩展的二进制大小。
3. 优化成果:显著减小二进制大小
通过上述一系列优化措施,Lyft 工程师成功地将其应用扩展的二进制大小从 45MB 减少到了 15MB,减少了 30MB。虽然 30MB 的减少对于服务端或桌面应用程序来说并不重要,但它相当于 200MB“安全”大小限制的 15%,这对于移动应用来说是一个非常显著的改进。
4. 其他挑战与解决方案
除了上述核心挑战外,Lyft 工程师在开发应用扩展的过程中还面临着其他一些挑战,例如:
4.1. 区域支持:确保扩展在所有地区可用
Lyft 需要确保其应用扩展在所有支持的地区都能正常工作,这需要仔细处理本地化和国际化问题。
4.2. APPLICATION_EXTENSION_API_ONLY
构建设置:确保代码的兼容性
Lyft 工程师还探讨了 APPLICATION_EXTENSION_API_ONLY
构建设置的效果,以确保应用扩展的代码与主应用的代码兼容。
4.3. SiriKit 特性:扩展应用功能
Lyft 还利用 SiriKit 特性,进一步扩展了应用扩展的功能,允许用户通过 Siri 语音助手与 Lyft 应用进行交互。
5. 启示与总结
Lyft 在iOS 应用扩展开发过程中所面临的挑战和解决方案,为其他开发者提供了宝贵的经验。以下是一些关键的启示:
- 深入的依赖关系分析至关重要: 了解应用的依赖关系是优化性能的关键。使用工具进行依赖关系分析可以帮助开发者找出性能瓶颈,并采取相应的优化措施。
- 精确的性能测量必不可少: 仅仅分析依赖关系是不够的,还需要使用工具精确测量每个模块对性能的影响,以便做出明智的决策。
- 必要时可以采取激进的优化措施: 在某些情况下,为了达到最佳的性能,可能需要采取激进的优化措施,例如代码复制。
- 关注细节,持续优化: 应用扩展的开发是一个持续优化的过程,开发者需要关注细节,不断改进代码,以提供最佳的用户体验。
Lyft 的案例表明,在资源有限的情况下,通过深入的分析、精细的优化和持续的努力,开发者仍然可以创建出卓越的应用扩展,为用户提供优质的服务。这不仅是一场技术挑战,更是一场对卓越用户体验的追求。
结论:
Lyft 的 iOS 应用扩展开发之旅,不仅展现了技术团队在面对挑战时的创新能力和解决问题的决心,也揭示了移动应用开发中一些不为人知的复杂性。通过深入的依赖关系分析、精确的性能测量以及必要的代码优化,Lyft 成功地克服了 iOS 应用扩展的资源限制,并为用户提供了卓越的体验。他们的经验为其他开发者提供了宝贵的参考,也提醒我们,在移动应用开发中,细节决定成败,持续优化是关键。未来,随着移动技术的不断发展,我们期待看到更多创新和突破,为用户带来更加便捷和高效的应用体验。
参考文献:
- Challenges of Creating iOS App Extensions at Lyft: https://www.infoq.com/news/2024/12/lyft-ios-maps-extension/
Views: 0