Modular Libraries in iOS

The Flurry SDK uses a dynamically-linked modular library design which breaks up features into different archives. This helps developers with large applications make sure that their application size is as small as possible by avoiding unnecessary libraries. We frequently get asked about how to implement dynamically-linked modular libraries in iOS so here is how it works.

Why modular libraries?

The Flurry SDK has grown considerably since its first release. New analytics and new advertising products were introduced with AppCircle and AppCircle Clips. Keeping developers in mind, we want to provide you with functionality necessary to accomplish your goals but not require you to carry the weight of all functionality if there's something that would go unused. For example, some developers use Analytics while some use Analytics and AppCircle. Others may use Analytics, AppCircle, and AppCircle Clips. The solution was to partition the existing library into smaller modular libraries that could be layered onto a core Analytics library.

Analytics is our core SDK library and it is the library responsible for communicating session data and ad data between our servers and apps. A request/response action takes place upon start and optionally upon pause or close of an app. Each request reports session data and the response contains a shared buffer filled with ad data which is relayed to each enabled ad library. Our servers currently receive 25,000 requests per second and growing, so this communication design decision (through a single communications point in the Analytics library) was made to keep traffic between our servers and apps efficient. This also creates asymmetric library dependencies since, for instance, Analytics can operate with or without AppCircle but AppCircle cannot operate without Analytics.

How modularization was accomplished

In AppCircle, the AppCircle library must be enabled.

This call above serves two purposes. First, it tells Analytics that AppCircle is being used so Analytics will request ad data on behalf of AppCircle. Second, it provides Analytics with a delegate, giving it access into the AppCircle library. The delegate is used as a callback to relay the ad data buffer into AppCircle to create the ads it provides through its API.

In Analytics, we maintain the delegate callback into AppCircle. The delegate is purposely declared an NSObject. This is set by AppCircle's setAppCircleEnabled method described above.

Then in Analytics, the delegate to AppCircle is tested and its callback is invoked with the ad data buffer as shown below. If AppCircle is not enabled then this collaboration with AppCircle is skipped altogether.

Declaring the delegate as NSObject and testing for the callback selector avoids any hard dependency to AppCircle, allowing Analytics to operate with or without AppCircle present. This pattern is also used for AppCircle Clips and future modular libraries in the works.

Modularizing our libraries significantly reduces the size of the Analytics library from a previous 6mb file to 1.7mb currently and allows layering any or all of our ad libraries on top of the Analytics library, so developers can optimize the amount Flurry library code they are linking into their applications. And because server communication remains the responsibility of Analytics during start, pause, or close of an app, our service can to continue to perform well as the traffic scales upward.