Egg Roll fund is an independent fund sales platform of Snowball. Egg Roll Fund (hereinafter referred to as Egg Roll) is one of the earlier projects using Swift. From Swift 2.0 version to the current 4.0.3, it has been waiting for static packaging feature. Swift finally supports static packaging after the Xcode9 upgrade.

As we know, dynamic libraries are for code sharing and resource sharing. In iOS, however, Apple does not recommend using dynamic libraries, which can affect app startup time. In addition, the excessive number of dynamic libraries may cause dyLD crashes on iOS 9 devices.

Because egg roll is managed by CocoaPods and Carthage, the transformation needs to be carried out separately for the dependency libraries managed by CocoaPods and Carthage. Before we started, other companies were already using Xcodeproj for static library packaging by manually adapting scripting. We’re just waiting for the release of CocoaPods1.5 (Swift Static Libraries support).

| CocoaPods

After upgrading CocoaPods to the latest version, modify your Podfile:

The main thing is to remove use_frameworks! To use_modular_headers! After pod install, Xcode is a red, sure enough there is still a pit!

The error is as follows:

After several twists and turns, the problem was found to be:

  • The bridging-header import lib header and lib Module have circular references;

The solution is simple: remove the references to the dependent packages in bridging-header. But it’s hard to figure out why.

First, the new CocoaPods1.5 property use_Modular_headers! To turn all pods into Modular modules. Modular is imported directly into Swift, without needing to be bridged through the bridge-header. Therefore, there is the problem of repeated references.

The problem of Modular Headers is addressed by CocoaPods Blog (Note 3). In the early days, to enable most libraries to pack Pods, CocoaPods used Header Search Paths to enable any Header files imported through un-namespaced to compile successfully. When pod install is installed, the pod path is set to Header Search Paths instead of User Header Search Paths, so that no error will be reported even if #import<> is referenced.

Second, the keyword use_frameworks that was previously used in Podfile! Package lib as umbrella Framework. Now change to static Library and manually set DEFINES_MODULE to true to turn on Modular or use_modular_headers! , which will cause the header lookup of the pod to fail. To do this, CocoaPods 1.5 cancels Modular casting.

This needs to explain the concept of the framework.

Static libraries in iOS include static library and static Framework. Dynamic libraries also include dynamic library and Dynamic Framework. Library and Framework can be described as an inclusive relationship. The Framework is actually a special Bundle containing not only the share Library but also xiBs, images, property lists, etc.

The above framework belongs to the Standard Framework and Umbrella Framework is used by CocoaPods. It is understood as a framework containing the framework. For details, see the Dynamic Library Programming Topics (Note 4) and Umbrella Header’s application to the Framework (Note 5).

After the framework, explain umbrella Header and Modular Headers, which are both concepts in the LLVM Module system. The LLVM Module system, Modules for Swift article says:

At the same time, Swift Module System is a customized version of LLVM Module System.

After removing the bridging-header reference, there is one more manual work that needs to be modified. Since Swift comes with a hidden namespace, lib packages referred to via bridge-header are in the project namespace and changed to Modular, which triggers the corresponding method loss error and requires manual import of the relevant library in the file header.

Another minor problem is when your Swift project happens to have code for OC (not a dependent library) if it introduces a Modular library. So, congratulations, this will also trigger a Modular Header Not define Error. Because OC code can only be called by Swift through the bridge-header, when OC code references the Modular library, it causes Modular reference collisions and compilation failures.

Modular_headers => false for the corresponding library. The Swift file is the most appropriate.

At this point, CocoaPods’ dependency packages are static.

| Carthage

Carthage does not currently support Swift static libraries, but it does provide a python scripted static library package. Creating a swift static library using libtool is not a problem. The generated static libraries do not need to be embedded into the Framework. Add them to the Link Binary with libraries.

| effect

At present, OC and Swift dependencies in the project are all packaged into static libraries. The OC part has been launched in 5.3, and the static packages of Swift library have not been integrated into the main branch.

  • All lib packages were changed to static packaging, and premain consumption was reduced from 5900+ms to 1300+ms in real iPhone 6 Plus tests.

  • According to itunesConnect statistics, the downloaded packages using OC static library are reduced from 35.2m to 30M, and the installed packages are reduced from 57.9m to 46.9m.

| reference

Note 1 Optimizing App Startup Time

Developer.apple.com/videos/play…

Note 2: Crash

Github.com/artsy/eigen…

Note 3: CocoaPods Blog

Blog.cocoapods.org/CocoaPods-1…

Note 4: Dynamic Library Programming Topics

Developer.apple.com/library/arc…

Note 5: Umbrella Header in the application of the framework blog.startry.com/2015/08/25/…

Note 6: Modules for Swift

Andelf. Making. IO/blog / 2014/0…

| there’s another thing

Snowball’s engineer team is recruiting Java engineers, operation and maintenance development engineers, test development engineers, algorithm engineers. Interested students can check the original text to see the specific positions and requirements, waiting for you.