RxSwift
取り入れたけどまだ慣れてない人向け
なんかのヒントになれば幸いです。
Delegate
RxSwift使ってたら自前Delegate
はclosure
は作らなくなってくると思います
普通の書き方
class SampleViewController: UIViewController, SampleViewDelegate {
@IBOutlet weak var view: SampleView!
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: SampleViewDelegate
func sendMessage(message: String) {
print("Did select : \(message)")
}
}
class SampleViewDelegate {
func sendMessage(message: String)
}
class SampleView: UIView {
weak var delegate: SampleViewDelegate?
private func didSelect() {
delegate?.sendMessage("message")
}
}
Rxを取り入れた書き方
import RxSwift
class SampleViewController: UIViewController {
@IBOutlet weak var view: SampleView!
override func viewDidLoad() {
super.viewDidLoad()
view.rx_message
.subscribeNext { [ unowned view] message in
print("Did select : \(message)")
}
.addDisposableTo(rx_disposeBag)
}
}
class SampleView: UIView {
// ここでは`PublishSubject`を使っていますが、
// イベントの取得だけでなく、値の保持をしたいなら`Variable`を使うのがいいです
let rx_message = PublishSubject<String>()
private func didSelect() {
rx_message.on(.Next("message"))
}
}
Delegate Extensionを作ってみる
RxSwiftの記述を参考に、DelegateメソッドをObserverで返せるようにしてみます
例としてUINavigationControllerのExtensionをあげます
extension UINavigationController {
var rx_willShowViewController: Observable<(UIViewController, Bool)> {
return rx_delegate.observe("navigationController:willShowViewController:animated:")
.map { a in
// 引数に渡したい値を返します
return (a[1] as! UIViewController, a[2] as! Bool)
}
}
var rx_didShowViewController: Observable<(UIViewController, Bool)> {
return rx_delegate.observe("navigationController:didShowViewController:animated:")
.map { a in
// 引数に渡したい値を返します
return (a[1] as! UIViewController, a[2] as! Bool)
}
}
}
RxSwiftに用意されてる便利なObserverたち
ここからは意外となんでもあるな、というものを紹介します。
RxSwift
は結構Observer
が用意されています。
主によく使ったもののみの紹介とさせていただきます。ここにないのもたくさんあります。
コード書く際に、まずはObserver
がないか試してみるといいと思います。
ボタンのタップイベント
普通の書き方
class SampleViewController: UIViewController {
@IBOutlet weak var button: UIButton!
private var flag = false
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self, action: #selector(SampleViewController.onClickPushButton), forControlEvents: .TouchUpInside)
}
func onClickPushButton(sender: UIButton) {
if flag {
print("did tap")
}
}
}
Rxを取り入れた書き方
import RxSwift
class SampleViewController: UIViewController {
@IBOutlet weak var button: UIButton!
private var flag = false
override func viewDidLoad() {
super.viewDidLoad()
button.rx_tap
.filter {[unowned self] self.flag}
.subscribeNext {
print("did tap")
}
.addDisposableTo(button.rx_disposeBag)
}
}
UIControlEvents
もあります
Rxを取り入れた書き方
import RxSwift
class SampleViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button.rx_controlEvent(UIControlEvents.TouchUpInside)
.subscribeNext { [unowned self] in
print("button TouchUpInside!")
}
.addDisposableTo(button.rx_disposeBag)
}
}
NSNotificationCenter
普通の書き方
class SampleViewController: UIViewController {
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "notificationObserve:", name: AVPlayerItemDidPlayToEndTimeNotification, object: playerItem)
}
func notificationObserve(notification: NSNotification) {
print("notificationObserve : \(notification)")
}
}
Rxを取り入れた書き方
import RxSwift
class SampleViewController: UIViewController {
deinit {
// rx_disposeBagは開放されるのでremoveの必要なし
}
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().rx_notification(AVPlayerItemDidPlayToEndTimeNotification, object: nil)
.subscribeNext { [ unowned view] notification in
print("rx_notification : \(notification)")
}
.addDisposableTo(rx_disposeBag)
}
}
UIScrollView. contentOffset
普通の書き方
class SampleViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
}
func scrollViewDidScroll(scrollView: UIScrollView) {
print("scrollViewWillBeginDragging \(scrollView.contentOffset)")
}
}
Rxを取り入れた書き方
class SampleViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.rx_contentOffset
.subscribeNext { [weak self] contentOffset in
// contentOffset値の変化時に取得
print("rx_contentOffset : \(contentOffset)")
}
.addDisposableTo(rx_disposeBag)
}
}
Gesture
普通の書き方
class SampleViewController: UIViewController {
@IBOutlet weak var view: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: "tapGesture:")
view.addGestureRecognizer(tapGesture)
}
func tapGesture(gesture: UIGestureRecognizer) {
print("gestureのtapイベントを取得")
}
}
Rxを取り入れた書き方
class SampleViewController: UIViewController {
@IBOutlet weak var view: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer()
tapGesture.rx_event
.map(void) // 引数使わない場合はmapしてしまう
.subscribeNext {
print("gestureのtapイベントを取得")
}
.addDisposableTo(view.rx_disposeBag) // viewが持つ`rx_disposeBag`を使うと開放時にわかりやすい
view.addGestureRecognizer(tapGesture)
}
}
NSURLSession
多くなってきたのでちょっと駆け足で。
↓取得してObserver
にして返すのも便利です
private func getData() -> Observable<NSData> {
let url = NSURL(string: "https://xxxx")!
return NSURLSession.sharedSession()
.rx_data(NSURLRequest(URL: url))
.take(1)
}
UISlider
slider.rx_value.asObservable()
.subscribeNext { value in
print("Sliderの値変更時に\(value)取得")
}
.addDisposableTo(slider.rx_disposeBag)
以上になります。
書き慣れてない文章でごめんなさい。
自分もまだまだ人のを真似ることしかできないので知らない部分だらけです。
思いついたらどんどん足していきます。
なにかありましたらお気軽にご教授ください。
なにかの参考にさればさいわいです。