Another cool thing about ios-oss is how it manages dependencies. Usually you have a lot of dependencies, and it’s good to keep them in one place, and inject it to the objects that need.
The Environment is simply a struct that holds all dependencies throughout the app
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/** A collection of **all** global variables and singletons that the app wants access to. */ publicstructEnvironment{ /// A type that exposes endpoints for fetching Kickstarter data. publiclet apiService: ServiceType
/// The amount of time to delay API requests by. Used primarily for testing. Default value is `0.0`. publiclet apiDelayInterval: DispatchTimeInterval
/// A type that exposes how to extract a still image from an AVAsset. publiclet assetImageGeneratorType: AssetImageGeneratorType.Type
/// A type that stores a cached dictionary. publiclet cache: KSCache /// ... }
Then there’s global object called AppEnvironment that manages all these Environment in a stack
publicstructAppEnvironment{ /** A global stack of environments. */ fileprivatestaticvar stack: [Environment] = [Environment()]
/** Invoke when an access token has been acquired and you want to log the user in. Replaces the current environment with a new one that has the authenticated api service and current user model. - parameter envelope: An access token envelope with the api access token and user. */ publicstaticfunclogin(_ envelope: AccessTokenEnvelope) { replaceCurrentEnvironment( apiService: current.apiService.login(OauthToken(token: envelope.accessToken)), currentUser: envelope.user, koala: current.koala |> Koala.lens.loggedInUser .~ envelope.user ) }
/** Invoke when we have acquired a fresh current user and you want to replace the current environment's current user with the fresh one. - parameter user: A user model. */ publicstaticfuncupdateCurrentUser(_ user: User) { replaceCurrentEnvironment( currentUser: user, koala: current.koala |> Koala.lens.loggedInUser .~ user ) }
// Invoke when you want to end the user's session. publicstaticfunclogout() { let storage = AppEnvironment.current.cookieStorage storage.cookies?.forEach(storage.deleteCookie)
// The most recent environment on the stack. publicstaticvar current: Environment! { return stack.last }
}
Then whenever there’s event that triggers dependencies update, we call it like
1 2 3 4 5
self.viewModel.outputs.logIntoEnvironment .observeValues { [weakself] accessTokenEnv in AppEnvironment.login(accessTokenEnv) self?.viewModel.inputs.environmentLoggedIn() }
The cool thing about Environment is that we can store and retrieve them
1 2 3 4 5 6
// Returns the last saved environment from user defaults. publicstaticfuncfromStorage(ubiquitousStore: KeyValueStoreType, userDefaults: KeyValueStoreType) -> Environment { // retrieval