Last active
July 12, 2019 19:22
-
-
Save rozd/1fd162d78d1a02df4a4817d3c11e4525 to your computer and use it in GitHub Desktop.
CurrentUser Swift implementation for iOS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: 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: "[email protected]", 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