Swift package offering a simple in-memory bucket into which services (i.e. objects) can be registered and retrieved.
- Add this Swift package to your Xcode project's list of Swift packages by means of this repo's URL.
- Select the target(s) that you would like to add this Swift package to.
The purpose of this Swift package is to offer a means by which an application can initialise and register all of its services into an in-memory bucket at start-up. Why? So that the application's view controllers and tests can obtain these services without having to concern themselves with the details of how these services are initialised.
The main class offered by this Swift package is the ServiceLocator class. This class defines three methods as follows:
addService(service:)
– Adds the given service to the service locator.addModule(module:)
– Adds each of the services defined in the given Module to the service locator.getServiceOfType(type:)
– Gets the service of the specified type from the service locator.
Let's assume, for the purpose of example, that we're going to register services into a service locator grouped by modules rather than registering services individually. Let's assume also that our application consists of two modules – ModuleA
and ModuleB
– and ModuleA
defines a service which ModuleB
depends on. Then, firstly, ModuleA
will look like this:
import ServiceLocator
class ModuleA: Module {
func registerServices(in serviceLocator: ServiceLocator) throws {
try serviceLocator.addService(ServiceA())
}
}
Secondly, ModuleB
will look like this:
import ServiceLocator
class ModuleB: Module {
func registerServices(in serviceLocator: ServiceLocator) throws {
let serviceA = try serviceLocator.getServiceOfType(ServiceA.self)
let serviceB = ServiceB(serviceA)
try serviceLocator.addService(serviceB)
}
}
Lastly, the ServiceLocator
object will be defined as follows:
let serviceLocator = ServiceLocator()
try serviceLocator.addModule(ModuleA())
try serviceLocator.addModule(ModuleB())
The only two places where services should be sought out from a ServiceLocator
object (once it has been defined and all services have been added to it) are the application's view controllers and test classes. All other calls to the ServiceLocator.getServiceOfType(type:)
method are considered an abuse.
Assume that a view controller or test class has access to a ServiceLocator
object named serviceLocator
. A service is retrieved from this ServiceLocator
object as follows:
@Inject(via: serviceLocator) var someService: SomeService