Skip to content

Instantly share code, notes, and snippets.

@stulevine
Created June 3, 2017 15:06
Show Gist options
  • Save stulevine/a208478bf51cbf9689d805faa0770583 to your computer and use it in GitHub Desktop.
Save stulevine/a208478bf51cbf9689d805faa0770583 to your computer and use it in GitHub Desktop.
// A Playground that shows how to use protocol extensions to do Dependency Injection
import UIKit
import PlaygroundSupport
enum InjectorType: String {
case mainType
case mocType
}
protocol MyProtocol {
var count: Int { get }
var view: UIView { get set }
func doSomething(withSring string: String)
}
protocol ManagerInjected { }
class MyClass: MyProtocol {
static let shared = MyClass()
public var view = UIView()
private var internalCount: Int
private var someString: String
public var count: Int {
self.internalCount += 1
return self.internalCount
}
private init() {
print("Main class initialized")
someString = "here I am"
internalCount = 0
view.backgroundColor = .lightGray
}
public func doSomething(withSring string: String) {
print("Look ma, no hands: \(string)")
}
}
class MOCMyClass: MyProtocol {
static let shared = MOCMyClass()
public var view = UIView()
private var internalCount: Int = 0
public var count: Int {
self.internalCount += 10
return self.internalCount
}
public func doSomething(withSring string: String) {
print("Look MOC, no hands and I'm MOC'ing you with \(string)")
}
private init() {
print("MOC class initialized")
}
}
struct ManagerInjector {
static var manager: (InjectorType)->MyProtocol = {
injectorType in
switch injectorType {
case .mainType: return MyClass.shared
case .mocType: return MOCMyClass.shared
}
}
private init() { }
}
extension ManagerInjected {
var inject: (InjectorType) -> MyProtocol { get { return ManagerInjector.manager } }
}
extension ManagerInjected where Self: UIViewController {
@discardableResult func setupMyView(managerType: InjectorType = .mainType) -> MyProtocol {
let manager = inject(managerType)
view.addSubview(manager.view)
manager.view.backgroundColor = UIColor.blue.withAlphaComponent(0.75)
manager.view.frame = CGRect(x: 10, y: view.frame.height, width: view.frame.width - 20, height: 100)
return manager
}
func showView(managerType: InjectorType = .mainType) {
let manager = inject(managerType)
let deltaY = manager.view.frame.origin.y == view.frame.height ? -manager.view.frame.height : manager.view.frame.height
UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseInOut, animations: {
manager.view.frame.origin.y += deltaY
}, completion: nil)
}
}
// How to use this Dependency Inject in a class to conforms to the protocol
class SomeViewController: UIViewController, ManagerInjected {
var myManager: MyProtocol?
var bottomConstraint = NSLayoutConstraint()
lazy var button: UIButton = {
let button = UIButton(type: UIButtonType.infoLight)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget(self, action: #selector(showInjectedView), for: .touchUpInside)
return button
}()
init() {
super.init(nibName: nil, bundle: nil)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
commonInit()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
showMeTheMoney()
}
func commonInit() {
view.backgroundColor = .white
view.addSubview(button)
view.frame = CGRect(x: 20, y: 50, width: 375, height: 600)
button.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10).isActive = true
button.topAnchor.constraint(equalTo: view.topAnchor, constant: 10).isActive = true
myManager = setupMyView()
}
func showMeTheMoney() {
guard let manager = myManager else { return }
manager.doSomething(withSring: "some fun stuff")
print("\(manager.count)")
print("\(manager.count)")
print("\(manager.count)")
}
func showInjectedView() {
showView()
}
}
let vc = SomeViewController()
PlaygroundPage.current.liveView = vc.view
PlaygroundPage.current.needsIndefiniteExecution = true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment