Created
May 5, 2020 21:16
-
-
Save chefnobody/41f8e6bc6e529710514ca18dab052fa8 to your computer and use it in GitHub Desktop.
Study-Combine-Refactor-To-Combine
This file contains 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
import Combine | |
import PlaygroundSupport | |
import UIKit | |
/// A line by line walk through of the following Combine example: | |
/// https://useyourloaf.com/blog/getting-started-with-combine/ | |
class TermsOfUseViewController: UIViewController { | |
// Some state: | |
@Published private var acceptedSwitch1: Bool = false | |
@Published private var acceptedSwitch2: Bool = false | |
@Published private var text: String = "" | |
// Publisher combining the above ^^ | |
private var validToSubmit: AnyPublisher<Bool, Never> { | |
return Publishers.CombineLatest3($acceptedSwitch1, $acceptedSwitch2, $text) | |
.map { switch1, switch2, text in | |
return switch1 && switch2 && !text.isEmpty | |
}.eraseToAnyPublisher() | |
} | |
// Subscribers to streams: | |
private var switch1Stream: AnyCancellable? | |
private var switch2Stream: AnyCancellable? | |
private var textStream: AnyCancellable? | |
private var validationStream: AnyCancellable? | |
let switch1: UISwitch = { | |
let s = UISwitch() | |
s.translatesAutoresizingMaskIntoConstraints = false | |
s.layer.borderColor = UIColor.red.cgColor | |
s.layer.borderWidth = 2.0 | |
return s | |
}() | |
let switch2: UISwitch = { | |
let s = UISwitch() | |
s.translatesAutoresizingMaskIntoConstraints = false | |
s.layer.borderColor = UIColor.blue.cgColor | |
s.layer.borderWidth = 2.0 | |
return s | |
}() | |
let textField: UITextField = { | |
let tf = UITextField() | |
tf.translatesAutoresizingMaskIntoConstraints = false | |
tf.layer.borderColor = UIColor.green.cgColor | |
tf.layer.borderWidth = 2.0 | |
return tf | |
}() | |
let button: UIButton = { | |
let b = UIButton() | |
b.translatesAutoresizingMaskIntoConstraints = false | |
b.setTitle("Submit", for: .normal) | |
b.setTitleColor(UIColor.blue, for: .normal) | |
b.setTitleColor(UIColor.red, for: .disabled) | |
return b | |
}() | |
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { | |
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) | |
view.backgroundColor = UIColor.white | |
// Setup actions | |
switch1.addTarget(self, action: #selector(switch1Changed(_:)), for: .valueChanged) | |
switch2.addTarget(self, action: #selector(switch2Changed(_:)), for: .valueChanged) | |
textField.addTarget(self, action: #selector(textChanged(_:)), for: .editingChanged) | |
button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside) | |
// Set up sinks on streams | |
switch1Stream = $acceptedSwitch1.sink { value in | |
print("switch 1: \(value)") | |
} | |
switch2Stream = $acceptedSwitch2.sink { value in | |
print("switch 2: \(value)") | |
} | |
textStream = $text.sink { value in | |
print("text: \(value)") | |
} | |
validationStream = validToSubmit | |
.receive(on: RunLoop.main) | |
.assign(to: \.isEnabled, on: button) | |
} | |
required init?(coder: NSCoder) { | |
fatalError() | |
} | |
deinit { | |
switch1Stream?.cancel() | |
switch2Stream?.cancel() | |
textStream?.cancel() | |
validationStream?.cancel() | |
} | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
view.addSubview(switch1) | |
view.addSubview(switch2) | |
view.addSubview(textField) | |
view.addSubview(button) | |
setupConstraints() | |
} | |
@objc private func switch1Changed(_ sender: UISwitch) { | |
acceptedSwitch1 = sender.isOn | |
} | |
@objc private func switch2Changed(_ sender: UISwitch) { | |
acceptedSwitch2 = sender.isOn | |
} | |
@objc private func textChanged(_ sender: UITextField) { | |
text = sender.text ?? "" | |
} | |
@objc private func buttonTapped(_ sender: UIButton) { | |
print("you tapped the button") | |
} | |
private func setupConstraints() { | |
NSLayoutConstraint.activate([ | |
switch1.leadingAnchor.constraint(equalTo: view.leadingAnchor), | |
switch1.topAnchor.constraint(equalTo: view.topAnchor), | |
view.trailingAnchor.constraint(equalTo: switch1.trailingAnchor), | |
switch2.topAnchor.constraint(equalTo: switch1.bottomAnchor), | |
switch2.leadingAnchor.constraint(equalTo: view.leadingAnchor), | |
view.trailingAnchor.constraint(equalTo: switch2.trailingAnchor), | |
textField.topAnchor.constraint(equalTo: switch2.bottomAnchor), | |
textField.leadingAnchor.constraint(equalTo: view.leadingAnchor), | |
view.trailingAnchor.constraint(equalTo: textField.trailingAnchor), | |
textField.heightAnchor.constraint(equalToConstant: 44), | |
button.topAnchor.constraint(equalTo: textField.bottomAnchor), | |
button.leadingAnchor.constraint(equalTo: view.leadingAnchor), | |
view.trailingAnchor.constraint(equalTo: button.trailingAnchor), | |
button.heightAnchor.constraint(equalToConstant: 44) | |
]) | |
} | |
} | |
let vc = TermsOfUseViewController() | |
// reigns in the Keyboard | |
vc.preferredContentSize = vc.view.frame.size | |
PlaygroundPage.current.liveView = vc |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment