9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RxSwiftでクロージャを減らす: APIリクエストのcompletionHandlerをObservableにしてみる

9
Posted at

RxSwiftを適用する箇所として、クロージャをObservableに切り替えるのが最近良いなと思ったので掲載。

APIクライアントからレスポンスを受けてUIを更新する操作はクロージャを使いますがこれをObservableを使って書き換えてみました。

Before

import UIKit

class ViewController: UIViewController {
	private var label: UILabel!

	override func viewDidLoad() {
		super.viewDidLoad()

		label = UILabel(frame: view.frame)
		label.numberOfLines = 10

		fetch(completion: { [weak self] data in
			guard let strongSelf = self else { return }
			strongSelf.label.text = String(data: data, encoding: .ascii)
			strongSelf.view.addSubview(strongSelf.label)
		})
	}

	private func fetch(completion: @escaping ((Data) -> Void)) {
		let request = URLRequest(url: URL(string: "https://www.google.com")!)
		URLSession.shared.dataTask(with: request, completionHandler: { data, _, error in
			guard
				error == nil,
				let data = data
			else { return }
			completion(data)
		}).resume()
	}
}

After

import UIKit
import RxSwift
import RxCocoa

class ViewController: UIViewController {
	private var label: UILabel!
	private let disposeBag = DisposeBag()

	enum MyError: Error {
		case APIClientFailed
	}

	override func viewDidLoad() {
		super.viewDidLoad()

		label = UILabel(frame: view.frame)
		label.numberOfLines = 10

		fetch().asObservable().subscribe(onNext: { [weak self] data in
			guard let strongSelf = self else { return }
			strongSelf.label.text = String(data: data, encoding: .ascii)
			strongSelf.view.addSubview(strongSelf.label)
		}).disposed(by: disposeBag)
	}

	private func fetch() -> Observable<Data> {
		return Observable<Data>.create { observer in
			let request = URLRequest(url: URL(string: "https://www.google.com")!)
			URLSession.shared.dataTask(with: request, completionHandler: { data, _, error in
				guard
					error == nil,
					let data = data
				else { return observer.on(.error(MyError.APIClientFailed)) }
				observer.on(.next(data))
				observer.on(.completed)
			}).resume()

			return Disposables.create()
		}
	}
}

こういう風に作っておくと、一度に2つ以上のエンドポイントにリクエストを送ってその内容をマージしたくなったり、リクエスト前後にバリデーションが必要になったりしたときにRxSwiftの能力を発揮して複雑性を増やさずにコードを書ける気がしています。

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?