Skip to content

Instantly share code, notes, and snippets.

@fumiyasac
Last active March 13, 2019 03:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fumiyasac/536e15bc8f3177dae975fd05db3283c9 to your computer and use it in GitHub Desktop.
Save fumiyasac/536e15bc8f3177dae975fd05db3283c9 to your computer and use it in GitHub Desktop.
RxSwiftでの実装練習の記録ノート(前編:Observerパターンの例とUITableViewの例) ref: https://qiita.com/fumiyasac@github/items/90d1ebaa0cd8c4558d96
target 'RxSwiftPracticeNote' do
use_frameworks!
# RxSwift使用時に必要なライブラリ
pod 'RxSwift'
pod 'RxCocoa'
# TableViewやCollectionViewのDataSourceをRxSwiftで扱うのに必要なライブラリ
pod 'RxDataSources'
・・・(省略)・・・
end
//データソースの定義
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Ramen>>()
override func viewDidLoad() {
super.viewDidLoad()
//データソースを元にしてセルの生成を行う
dataSource.configureCell = {_, tableView, indexPath, ramens in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = ramens.name
cell.detailTextLabel?.text = ramens.taste
cell.imageView?.image = ramens.image
return cell
}
//データソースの定義を元にセクションヘッダーを生成する ※動画サンプルと形式が違う部分
dataSource.titleForHeaderInSection = { (ds, section: Int) -> String in
return ds[section].model
}
//作成したデータと表示するUITableViewをBindして表示する
ramensData.ramens.bindTo(ramenTableView.rx.items(dataSource: dataSource)).addDisposableTo(disposeBag)
・・・(省略)・・・
}
//データソースの定義
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Ramen>>(
//データソースを元にしてセルの生成を行う
configureCell: { (_, tableView, indexPath, ramens) in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = ramens.name
cell.detailTextLabel?.text = ramens.taste
cell.imageView?.image = ramens.image
return cell
},
//データソースの定義を元にセクションヘッダーを生成する ※動画サンプルと形式が違う部分
titleForHeaderInSection: { dataSource, sectionIndex in
return dataSource[sectionIndex].model
}
)
override func viewDidLoad() {
super.viewDidLoad()
//作成したデータと表示するUITableViewをBindして表示する
ramensData.ramens.bind(to: ramenTableView.rx.items(dataSource: dataSource)).disposed(by: disposeBag)
・・・(以下省略)・・・
}
freewordWithNameObservable.bindTo(greetingLabel.rx.text).addDisposableTo(disposeBag)
freewordWithNameObservable.bind(to: greetingLabel.rx.text).disposed(by: disposeBag)
import UIKit
import RxDataSources
//ラーメンデータ定義用の構造体(Model層)
struct Ramen {
//取得データに関する定義
let name: String
let taste: String
let imageId: String
var image: UIImage?
//取得データのイニシャライザ
init(name: String, taste: String, imageId: String) {
self.name = name
self.taste = taste
self.imageId = imageId
image = UIImage(named: imageId)
}
}
//既存の独自型(RxDataSourcesで定義されているIdentifiableType型)を拡張する
extension Ramen: IdentifiableType {
typealias Identity = String
var identity: Identity { return imageId }
}
override func viewDidLoad() {
super.viewDidLoad()
//データソースを元にしてセルの生成を行う
dataSource.configureCell = {_, tableView, indexPath, ramens in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = ramens.name
cell.detailTextLabel?.text = ramens.taste
cell.imageView?.image = ramens.image
return cell
}
//作成したデータと表示するUITableViewをBindして表示する
ramensData.ramens.bindTo(ramenTableView.rx.items(dataSource: dataSource)).addDisposableTo(disposeBag)
//RxSwiftを利用してUITableViewDelegateを適用する
ramenTableView.rx.setDelegate(self).addDisposableTo(disposeBag)
//データソースの定義を元にセクションヘッダーを生成する
dataSource.titleForHeaderInSection = { (ds, section: Int) -> String in
return ds[section].model
}
}
//UITableViewCellのセル高さを設定する(UITableViewDelegate)
extension RamenListController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return CGFloat(65)
}
}
//表示データ形式定義に関するPresenterクラス
class RamenPresenter {
//表示用のデータの具体的な設定をする
let ramens = Observable.just([
//引数(model: セクション名, items: [モデル構造体で定義する値の配列])
SectionModel(model: "醤油", items: [
Ramen(name: "豚骨醤油ラーメン",taste: "濃いめ", imageId: "sample005"),
Ramen(name: "喜多方ラーメン", taste: "あっさり", imageId: "sample009"),
Ramen(name: "チャーシューメン", taste: "あっさり", imageId: "sample010")
]),
SectionModel(model: "塩味", items: [
Ramen(name: "野菜たっぷりタンメン", taste: "あっさり", imageId: "sample007")
]),
SectionModel(model: "味噌", items: [
Ramen(name: "8番ラーメン味噌味", taste: "ふつう", imageId: "sample001"),
Ramen(name: "もやしそば味噌味", taste: "濃いめ", imageId: "sample008")
]),
SectionModel(model: "その他", items: [
Ramen(name: "台湾風まぜそば", taste: "濃いめ", imageId: "sample002"),
Ramen(name: "長崎ちゃんぽん", taste: "ふつう", imageId: "sample003"),
Ramen(name: "酸辣湯麺", taste: "ふつう", imageId: "sample004"),
Ramen(name: "トマトと野菜のラーメン", taste: "あっさり", imageId: "sample006")
])
])
}
let lastSelectedGreeting: BehaviorRelay<String> = BehaviorRelay<String>(value: "こんにちは")
・・・(途中省略)・・・
//アウトレットコレクションで接続したボタンに関する処理
greetingButtons.forEach { button in
//(bindTo)イベントのプロパティ接続をする ※bindToの引数内に表示対象のUIパーツを設定
//(DisposeBag)観測状態からの解放を行う
buttonsEnabledObservable.bind(to: button.rx.isEnabled).disposed(by: disposeBag)
//メンバ変数:lastSelectedGreetingにボタンのタイトル名を引き渡す
//(subscribe)イベントが発生した場合にイベントのステータスに応じての処理を行う
button.rx.tap.subscribe(onNext: { (nothing: Void) in
self.lastSelectedGreeting.accept(button.currentTitle!)
}).disposed(by: disposeBag)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment