Overcoming iOS App Extension Challenges: Insights from Lyft Engineers
2024-12-17
Author: Amelia
Introduction
In an insightful exploration by Lyft engineers Artur Stepaniuk and Max Husar, the complexities involved in developing efficient iOS app extensions have been laid bare.
Integration with Apple Maps
The Lyft app integrates seamlessly with Apple Maps, allowing users to access Lyft offers directly from the Maps interface. However, achieving this integration without breaching Apple's stringent RAM and binary size limitations poses a significant challenge.
Managing Dependencies
To maintain an optimal user experience, Lyft engineers have mastered the art of managing dependencies judiciously. This not only promotes code reuse across both the main app and its extension but also helps in optimizing the app's binary size and memory consumption.
Challenges with Binary Size and RAM
One of the major hurdles they face is the inability to use dynamic linking. This limitation necessitates the use of static linking, which, while vital for performance, inadvertently increases the app's binary size and overall memory requirements.
The implications of a larger binary size are profound—long download times can deter potential users. If the app hits the critical 200 MB download size limit, those attempting to install via cellular data will encounter an additional confirmation prompt, which could dissuade downloads altogether.
Furthermore, RAM constraints add another layer of complexity. The engineering team discovered that extensions could be confined to a mere 20 to 50 MB of RAM, a limitation influenced by factors such as the iOS version and device type.
Analyzing Dependency Graphs with Bazel
To tackle these challenges, the Lyft team undertook an in-depth analysis of their app's dependency graph. Employing Bazel, they utilized Graphviz to visualize data produced by Bazel, allowing them to pinpoint crucial modules that contribute aggressively to binary size and memory usage.
Binary Size Metrics
To provide robust metrics on binary size alterations, the team implemented the binary-size-diff tool, which facilitates a comparison of binary size changes between code branches. This enabled the engineers to meticulously assess the repercussions of adding or removing specific code dependencies.
Streamlining Dependencies
Additionally, the engineers leveraged Bazel's querying capabilities to uncover unnecessary dependencies. By issuing a command that maps the transitive dependencies between modules, they were able to identify and eliminate excess dependencies, streamlining their app's architecture.
In one instance, the Lyft team opted to replicate a service to create a simpler, minimalist dependency that alleviated reliance on larger modules.
Results and Conclusion
Their strategic approaches bore fruit, with the size of the app extension shrinking from 45 MB to a mere 15 MB. While this 30 MB reduction might seem trivial for larger software applications, it represents a transformative 15% decrease against the maximum "safe" download limit of 200 MB—a critical improvement for enhancing user engagement and installations.
The insights shared by the Lyft engineering team underscore the importance of meticulous analysis and innovative problem-solving in app development. As they continue to refine their approach to creating app extensions, their experience serves as a valuable lesson for developers facing similar challenges in the evolving landscape of mobile app development.