Important: This documentation is out of date but the project itself has been updated to work with Swift 5 and Xcode14
An example project showing embedded framework with conditional dynamic class loading based on scheme.
The interfaces to any dynamically loaded classes are defined in a seperate framework that is always available to the app. It is both embedded and linked with the app DynamicLoaderExampleApp.app.
public protocol AnInterfaceAvailableToApp {
static func doSomething()
static func doSomethingElse() -> String
}This is the framework that is conditionally included in the app. The framework is always embedded but not linked with the app DynamicLoaderExampleApp.app. It is "linked" with the framework that defines its interface DynamicLoader.framework.
Any class that we want to dynamically load must implement an interface that the app is aware of.
public class DynamicClassExample : AnInterfaceAvailableToApp {
public static func doSomething() {
print("loaded dynamic class")
}
public static func doSomethingElse() -> String {
return "Hello, World!"
}
}The framework is loaded before the class is retrieved by name.
let bundleURL = NSBundle.URLForResource("DynamicFramework", withExtension: "framework", subdirectory: "Frameworks", inBundleWithURL: NSBundle.mainBundle().bundleURL)
let bundle = NSBundle(URL: bundleURL)
bundle.load()Swift class names should include the module name.
let aClass = NSClassFromString("DynamicFramework.DynamicClassExample")The app uses the interfaces provided by the DynamicLoader.framework and nothing from DynamicFramework.framework directly.
guard let aConformingClass = aClass as? AnInterfaceAvailableToApp.Type else {
//the class was not loaded
return
}
//the class was loaded and we can do something
aConformingClass.doSomething()There is an additional build phase for the app that will conditionally remove dynamic framework DynamicFramework.framework depending on the scheme being run. This is often helpful for inlcuding additional code during development or testing but leaving it out of the a release.
if [ "${CONFIGURATION}" == "Release" ]; then
rm -rf "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Frameworks/DynamicFramework.framework"
fi