SwiftyLaunch Modules Overview
A SwiftyLaunch Module is a self-contained unit of code that is responsible for a specific feature or functionality of your app.
It should only contain the code that is relevant to fulfil the functionality of the module.
For example, if we take the AdsKit Module, it will only contain the code that is responsible for displaying ads in your application and nothing else.
A module exposes Views and View Models to other app modules, using the public
keyword that is defined within the module source code.
import GoogleMobileAds
public struct AdBanner: View {
public init(adUnitID: String) { /* ... */ }
public var body: some View { /* ... */ }
}
In order to use the AdBanner
View in your app, we would first have to add AdsKit
it to the Target
we want to use it in
After doing that, we can then import the module and use the AdBanner
View in our code.
import AdsKit // import the AdsKit module
struct ContentView: View {
var body: some View {
VStack {
AdBanner(adUnitID: "some-ad-unit-id") // use the publicly-defined AdBanner View
}
}
}
A module under the hood is a Framework project target (opens in a new tab) in Xcode, which has a up-stream working logic and is to be seen as a "dependency".
So, when a module X includes a module Y (as a "dependency"), it means that X can access anything that is public in Y. But Y does not have access to anything in X.
So, if we again take AdsKit as an example: AdsKit includes AnalyticsKit as one of its modules, in order to track events such as when a user views an ad.
Meaning that we can access features exposed by AnalyticsKit in AdsKit, such as the .capture
function.
So, when AdMob calls one of its delegate methods, we can capture it using AnalyticsKit.
import AnalyticsKit
import GoogleMobileAds
extension NativeAdBannerViewModel: GADNativeAdDelegate {
/// Track when your users views an ad
public func nativeAdDidRecordImpression(_ nativeAd: GADNativeAd) {
Analytics.capture(.info, id: "ad_impression", source: .adsKit)
}
/// Track when your users click on an ad
public func nativeAdDidRecordClick(_ nativeAd: GADNativeAd) {
Analytics.capture(.info, id: "ad_click", source: .adsKit)
}
}
If a part of the code is often used across multiple modules, it should be added to the SharedKit module, which represents the lowest common module of the app.
Here is a visual example of how the data flow works withing an app generated by SwiftyLaunch:
Module Structure
Every SwiftyLaunch Module follows the same semi-MVVM structure:
Creating a new Module
To add a new SwiftyLaunch Module, in Xcode go to File > New > Target.
In the dialog that appears, select Framework, and click on Next.
Enter Module's information and press on Finish.
After creation, delete the newly created folder (In the Alert dialog press "Move to Trash").
In Targets, create a new group with the same module name, and create a new Swift file in the group.
Make sure that the Swift file is belonging to the right module, by selecting the module in the right sidebar.
Now, to test it out, define a new function, but make sure to mark it with the public keyword.
// ModuleContent.swift
public func twoPlusTwo() -> Int {
return 4
}
Using the new Module
To call this function, we first need to make sure that the module is selected as a framework in the target we want to use it in.
The module will be added to to the App Target by default, but you can also include it in another module (in this example, AnalyticsKit).
Now to call the function, import the module in the file you want to use it in, and call the function.
import MyModule
import SwiftUI
struct ContentView: View {
var body: some View {
Text("\(twoPlusTwo())") // 4
}
}
Creating a Module via Tuist
If you're using the Tuist integration, refer to Defining a new module to see how to add a new module to your app.