A collection of shared Swift utilities. And no wheels reinvented. Nor knives.
This section contains Swift-specific terms like "framework", and ambiguous terms like "consumer". Other business terms like "module", and technical terms like "repo" (repository) are not included in this section.
- Framework: on a high level it means an isolate software unit that can be used by consumers. A "library", "package", or "SDK" means similar things.
- We prefer the term "framework" here because in Swift's world, a module is usually built to a
MyLibrary.framework
file. - Technical terms in
SPM
ispackage
andtarget
, and inCocoapods
they arepod
orspec
, andsubspec
.
- We prefer the term "framework" here because in Swift's world, a module is usually built to a
- Consumer: an application that references a framework by its interfaces (
@interface
orprotocol
), and they statically or dynamically linked ("embed" or not).
Please read the next section for the guideline of creating different frameworks inside this repo.
Package.swift contains the source of truth of our frameworks and their dependencies. The following documents should always reflect the implementation.
- Business: common features can be used by any Swift applications.
- Dependency: Swift only. Due to limited development resources, we only support a specific
Swift
version (and above).- A better approach is to create
CoreSwift51
,CoreSwift55
,CoreSwift57
etc. Core
is available on all platforms thatSwift
can compile, just make sure you have the rightSwift
version.- Please note that
Foundation
is NOT part of Swift itself! Types likeDate
are platform specific. We'll see it in other modules.
- A better approach is to create
- Business: a WIP logger.
- Dependency:
Core.Environment
.
- Business: common features can be used by any Swift applications that has Foundation implementation.
- Dependency:
- Foundation framework (Linux implementation may be different with Apple's own OSes).
Core
.
It is preferred to segregate your framework codebase into different modules. It could be targets
in SPM
, or subspec
in Cocoapods
.
A common practice is to divide your codebase by business goals, and dependencies.
Because dependencies are nested by nature, our modularized frameworks are also nested.
It is actually recommended to create different frameworks. However, practically, some package management tools like SPM
does not support multiple framework definition files (Package.swift
for SPM
, at least in 2023) in the same repo, and we are using SPM
here. So we use a single repo to minimize management cost.
This practice is NOT recommended for enterprises that have millions to burn; always do things properly, if you can afford it.
What goal(s) are you trying to achieve? If you have a framework that contains a Logger and an Obfuscater, while they both deal with Strings
, it's a bad idea to put them in the same framework.
Why? Because the consumer may or may not use both modules, and it's a waste of compile time, binary size, and runtime resource (if a module contains global instances) to include unused source files. By dividing your modules into different frameworks, you may also gain other benefits, for example making your dependencies more flexible (see the Moya
example below).
When building a module of a framework, it is crucial to understand what it depends on. This is because the consumer always wants minimized dependencies.
We should always try to minimize our dependencies, and segregate our codebase based on dependencies possible (usually it is). This is to avoid introducing unnecessary dependencies of dependencies to consumers.
Take a look at Moya, a networking middleware. It's core Moya
depends on Alamofire
, so it always comes with its own dependencies.
Other than that, a separated target CombineMoya
has the same dependencies, but it's segregated because a consumer may not use Combine
. The segregation results fewer files to compile, and lowers the Swift
version requirement, and so on.
And for different dependencies like RxSwift
and ReactiveSwift
, different targets RxMoya
and ReactiveMoya
were created.