Skip to content

Instantly share code, notes, and snippets.

@rizumita
Created July 27, 2019 12:40
Show Gist options
  • Save rizumita/79c235d6b1ce2b23b143835a4d69e101 to your computer and use it in GitHub Desktop.
Save rizumita/79c235d6b1ce2b23b143835a4d69e101 to your computer and use it in GitHub Desktop.
import UIKit
public typealias Send<A> = (A) -> ()
public typealias Receive<A> = (A) -> ()
public typealias Observe<A> = (@escaping Receive<A>) -> (ObserveToken)
public typealias OPipe<A> = (send: Send<A>, observe: Observe<A>)
public class ObserveToken: Hashable {
let uuid = UUID()
let receive: Any
init<A>(_ receive: @escaping Receive<A>) {
self.receive = receive
}
public func hash(into hasher: inout Hasher) {
hasher.combine(uuid)
}
public static func ==(_ lhs: ObserveToken, _ rhs: ObserveToken) -> Bool {
if lhs.uuid != rhs.uuid { return false }
return true
}
}
public func opipe<A>(_ type: A.Type = A.self) -> OPipe<A> {
let tokens = NSHashTable<ObserveToken>.weakObjects()
let observe: Observe<A> = { [weak tokens] receive in
let token = ObserveToken(receive)
tokens?.add(token)
return token
}
let send: Send<A> = { a in
tokens.allObjects.forEach { token in
guard let receive = token.receive as? Receive<A> else { return }
receive(a)
}
}
return (send, observe)
}
class MessageDraftViewController: UIViewController {
@IBOutlet weak var messageTextField: UITextField!
@IBOutlet weak var sendButton: UIButton!
var draft: MessageDraft = MessageDraft()
var messageTextFieldProxy: MessageDraftingProxyProtocol!
var messageProxy: MessageDraftingProxyProtocol!
var configureProxy: (MessageDraftViewController) -> () = { _ in }
private var observeTokens = [ObserveToken]()
override func viewDidLoad() {
super.viewDidLoad()
configureProxy(self)
observeTokens += [
messageProxy.observe { [weak self] update in
guard let this = self else { return }
this.draft = update(this.draft)
}
]
}
@IBAction func sendButtonTapped(_ sender: Any) {
messageTextField.resignFirstResponder()
print(draft.message.content)
}
}
protocol MessageDraftViewControllerConfigureProtocol {
func configure(_ controller: UIViewController)
}
class MessageDraftViewControllerConfigurator: MessageDraftViewControllerConfigureProtocol {
func configure(_ controller: UIViewController) {
guard let controller = controller as? MessageDraftViewController else { fatalError() }
controller.configureProxy = { controller in
let proxy = MessageProxy()
controller.messageProxy = proxy
controller.messageTextField.delegate = proxy
}
}
}
struct Message {
var content: String = ""
}
struct MessageDraft {
var message: Message
init() { message = Message() }
}
protocol MessageDraftingProxyProtocol {
var observe: Observe<(MessageDraft) -> MessageDraft> { get }
}
class MessageProxy: NSObject, MessageDraftingProxyProtocol, UITextFieldDelegate {
var observe: Observe<(MessageDraft) -> MessageDraft> { return pipe.observe }
private var pipe: OPipe<(MessageDraft) -> MessageDraft> = opipe()
func textFieldDidEndEditing(_ textField: UITextField) {
pipe.send { draft in
var draft = draft
draft.message.content = textField.text ?? ""
return draft
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment