Skip to content

Instantly share code, notes, and snippets.

@rozd
Last active July 12, 2019 19:22
Show Gist options
  • Save rozd/1fd162d78d1a02df4a4817d3c11e4525 to your computer and use it in GitHub Desktop.
Save rozd/1fd162d78d1a02df4a4817d3c11e4525 to your computer and use it in GitHub Desktop.
CurrentUser Swift implementation for iOS
//: Playground - noun: a place where people can play
import Foundation
// MARK: Infrastructure
/// Contract for remote user service
protocol UserService {
func signIn(completion handler: (User?) -> ())
}
class DefaultUserService: UserService {
func signIn(completion handler: (User?) -> ()) {
let user = UserEntity(id: "userId", email: "mail@example.com", firstName: "John", lastName: "Smith")
handler(user)
}
}
/// Contract for local user storage
protocol UserStorage {
func save(user: User)
func read() -> User?
}
class DefaultUserStorage: UserStorage {
func save(user: User) {
}
func read() -> User? {
return nil
}
}
// MARK: Model
/// User contract that used everywhere in API
protocol User {
var id: String { get }
var email: String { get }
var firstName: String { get }
var lastName: String { get }
}
/// User routines extensions
extension User {
var fullName: String {
return "\(firstName) \(lastName)"
}
}
/// User implementation, this struct could be considered as Value Object
struct UserEntity: User {
let id: String
let email: String
let firstName: String
let lastName: String
}
// MARK: Current User Contracts
/// Constract for current user
protocol CurrentUser: User {
func signIn(completion handler: (User?) -> ())
}
extension CurrentUser where Self == Current.User {
func signIn(completion handler: (User?) -> ()) {
service.signIn(completion: handler)
}
}
/// Contract for user that could be saved/restored
protocol StorableUser {
func save()
func read()
func fill(from user: User?)
}
extension StorableUser where Self == Current.User {
func save() {
storage.save(user: self)
}
func read() {
}
func fill(from user: User?) {
self.id = user?.id ?? ""
self.email = user?.email ?? ""
self.firstName = user?.firstName ?? ""
self.lastName = user?.lastName ?? ""
}
}
// MARK: Current User Implementation
/// Access point for current user
class Current {
}
/// Defines implementation for CurrentUser and StorableUser contracts, and holds its instance as singleton
extension Current {
static let user: CurrentUser = User(service: DefaultUserService(), storage: DefaultUserStorage())
class User: CurrentUser, StorableUser {
init(service: UserService, storage: UserStorage) {
self.service = service
self.storage = storage
let stored = self.storage.read()
self.id = stored?.id ?? ""
self.email = stored?.email ?? ""
self.firstName = stored?.firstName ?? ""
self.lastName = stored?.lastName ?? ""
}
let service: UserService
let storage: UserStorage
var id: String
var email: String
var firstName: String
var lastName: String
}
}
// MARK: Usage
Current.user.signIn { user in
if let user = user {
print("Logged in as \(user.fullName)")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment