Skip to content

Instantly share code, notes, and snippets.

@bsrz
Last active May 7, 2023 03:04
Show Gist options
  • Select an option

  • Save bsrz/210606d50ccd9870c1babf17233bf5e1 to your computer and use it in GitHub Desktop.

Select an option

Save bsrz/210606d50ccd9870c1babf17233bf5e1 to your computer and use it in GitHub Desktop.
func app() {
let idToken = ...
let baseUrl = ...
let configuration = Configuration(idToken: idToken, baseUrl: baseUrl)
do {
try Client.shared.preloadMedia()
let controller = Client.shared.start()
present(controller, animated: true)
} catch {
print(":boom: Unexpected error: \(error)") // Uh oh, you forgot to call `configure(with:)`
}
}
func app() {
let idToken = ...
let baseUrl = ...
let configuration = Configuration(idToken: idToken, baseUrl: baseUrl)
let scope = Client.shared.configure(with: configuration) // _must_ be called
scope.preloadMedia()
let controller = scope.start()
present(controller, animated: true)
}
struct Authentication {
var accessToken: String
var refreshToken: String
var tokenType: String
var expiry: UInt
}
public class Client {
public static let shared: Client = .init()
private init() { }
// MARK: - Configuration
private var configuration: Configuration!
public func configure(with configuration: Configuration) throws {
self.configuration = configuration
try self.authenticate()
}
// MARK: - Authentication
private var authentication: Authentication!
private func authenticate() throws {
guard configuration != nil else { throw ConfigurationError.mustBeConfigured }
self.authentication = /* using configuration.idToken and configuration.baseUrl */
}
// MARK: - UI
public func start() throws -> UIViewController {
guard configuration != nil else { throw ConfigurationError.mustBeConfigured }
guard authentication != nil else { throw AuthenticationError.mustBeAuthenticated }
let controller = ...
return controller
}
public func preloadMedia() throws {
guard configuration != nil else { throw ConfigurationError.mustBeConfigured }
guard authentication != nil else { throw AuthenticationError.mustBeAuthenticated }
// fetch media and cache it
...
}
}
public class Client {
public static let shared: Client = .init()
private init() { }
public func configure(with configuration: Configuration) -> AuthenticatedScope {
let authentication = authenticate(
with: configuration.idToken,
at: configuration.serviceBaseUrl
)
return AuthenticatedScope(authentication: authentication)
}
private func authenticate(with idToken: String, at baseUrl: URL) -> Authentication {
// Authenticate user
return Authentication(/* with obtained values */)
}
}
extension Client {
public class AuthenticatedScope {
private let authentication: Authentication
init(authentication: Authentication) {
self. authentication = authentication
}
// MARK: - UI
public func start() -> UIViewController {
let controller = ...
return controller
}
public func preloadMedia() {
// fetch media and cache it
...
}
}
}
struct Configuration {
var idToken: String
var baseUrl: URL
}
guard configuration != nil else { throw ConfigurationError.mustBeConfigured }
guard authentication != nil else { throw AuthenticationError.mustBeAuthenticated }
private var configuration: Configuration!
private var authentication: Authentication!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment