This demo project is here for educational purposes and contains mvp code, that can be vastly improved.
It demonstrates the following features:
- Lazy modules loading
- Modules merging
Both of them show you the ways of reducing the dynamic libaries count, which dyld
loads during the application start.
Another solution is to turn all modules from dynamic frameworks into static libraries, but this is not that fun =).
Build the project and check the contents of your LazyModulesExample.app/Frameworks
folder.
You will see Feature1.framework
, Feature2.framework
and MergedCore.framework
(and probably several libswift.dylib
s, depending on versions of your Xcode
and target iOS
).
During the application start only system libraries and MergedCore.framework
will be loaded into memory. Feature1.framework
and Feature2.framework
will be loaded on demand at runtime (i.e. lazily).
-
Launch the app and tap "LOAD FEATURE 1" or "LOAD FEATURE 2" button.
-
Check the console logs. You will see something like
!!!
Will load Feature1 if it is not loaded yet.
See dyld logs in the console.
...
!!!
dyld: loaded: /Users/username/Library/Developer/Xcode/DerivedData/LazyModulesExample-giiydmraztexwgcipbutixergqns/Build/Products/Debug-iphonesimulator/Feature1.framework/Feature1
In Feature1. Printing from class named: Protocol1Impl
What this means, is that dynamic linker (dyld
) loaded a framework from the disk into memory.
See LazyModulesLoader.m
for some implementation details.
- If you did not see what was mentioned above, then make sure 'Dynamic Library Loads' is enabled in 'Scheme -> Run -> Diagnostics', or pass 'DYLD_PRINT_LIBRRARIES' environment variable in 'Scheme -> Run -> Arguments -> Eviromnent Variables'.
Feature1
- lazily loaded module.Feature2
- lazily loaded module.Interfaces
- a mediator module to allow communication between feature modules (features do not depend on each other, they depend onInterfaces
).DI
- dependency injection module. Also implements lazy loading of other modules.Footprints
- module to feedDI
with information about which lazy module to load in response on aresolve()
request.MergedCore
- module in which we mergeDI
,Interfaces
andFootprints
.
Modules merging is based on the technique described in Amimono cocoapods plugin.
We merge DI
, Interfaces
and Footprints
into MergedCore
.
- See
MergedCore.xcconfig
with its-filelist
flag passed to the static linker (ld
). - See
Create filelist per architecture
build phase ofMergedCore
target to understand how this filelist gets filled. - See
Check for dublicated symbols absence
build phase ofLazyModulesExample
target to understand how we make sure no dublicated symbols get bundled in the application. This may happen if you accidentally break the project via copyingDI.framework
into theLazyModulesExample.app/Frameworks
folder and linkingLazyModulesExample.app/LazyModulesExample
againstDI.framework/DI
while still linking againstMergedCore.framework/MergedCore
.