일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- UIPresentationController
- base64 변환
- DevelopmentRegion
- 기존 앱
- url 관찰
- 스크롤 탭
- Android
- GeometryReader
- Tuist
- transformation.map
- swift #swift keychain #keychain 사용법
- development language
- swift
- 개발자 면접
- Side Menu
- scrolling tab
- Swift Package Manager
- ios
- ViewBuilder
- SwiftUI
- convert base64
- DataBinding
- List
- pod install
- notifychanged
- url 추적
- detect url
- oberve url
- UIViewControllerTransitioningDelegate
- 상단 탭바
- Today
- Total
버그 잡이
RxSwift로 tableView 구현하기 본문
RxSwift로 tableView를 보다 간단하게 구현할 수 있습니다.
구현 방식에도 여러 가지가 있는데
크게
-
tableView.rx.items 에 bind하는 방법
-
RxDataSource를 사용하는 방법
이렇게 두 가지 방법이 있습니다.
tableView.rx.items
첫번째 방법은 가장 기본적인 방법으로 간단한 tableView 형태를 구현할 때 사용할 수 있습니다.
data를 tableView에 bind하는 방식으로 기존에 Rx를 활용하여 data와 button을 바인딩 했던 것과 별반 다르지 않습니다.
차이점이 있다면 클로저 안에서 index, model, cell 변수가 주어져 이를 활용한 작업이 가능합니다.
data의 특정 요소를 text로 넣는다거나
index에 따라 각기 다른 특정을 주는 것이 가능하겠죠?
let data = Observable<[String]>.just(["first element", "second element", "third element"])
data.bind(to: tableView.rx.items(cellIdentifier: "Cell")) { index, model, cell in
cell.textLabel?.text = model
}
.disposed(by: disposeBag)
또 cellIdentifier를 통해서 등록된 cell을 가져오는 것을 볼 수 있습니다.
이는 위와 같은 방식 뿐만 아니라 아래와 같이 3가지 형태로 cell을 가져올 수 있습니다.
autoLayout에 있는 cell 인지 class에 있는 cell 인지에 따라서 어떤 방법을 사용할지 달라지겠죠?
-
rx.items(cellIdentifier:String)
-
rx.items(cellIdentifier:String:Cell.Type:_:)
-
rx.items(_:_:)
RxDataSource
그런데 위와 같은 tableView.rx.items 방식으로는
1) section이 여러 개인 경우
2) 경우에 따라 다양한 cell을 사용해야하는 경우
에 대해서 대처할 수 없습니다.
이럴때는 RxDataSource를 사용해야 합니다.
이는 우리가 UITableViewDataSource에서 출력될 cell을 정의했던 것 처럼
RxDataSource에서 원하는 형태의 cell을 정의할 수 있습니다.
여러 개의 cell을 등록해서 쓸 수도 있고, section이 있는 경우도 대응할 수 있습니다.
#사용법
1. 사용할 dataSource를 미리 정의하고
let dataSource = RxTableViewSectionedReloadDataSource<SectionOfCustomData>(
configureCell: { dataSource, tableView, indexPath, item in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = "Item \(item.anInt): \(item.aString) - \(item.aCGPoint.x):\(item.aCGPoint.y)"
return cell
})
2. section도 정의해서 넣어줍니다.
let sections = [
SectionOfCustomData(header: "First section", items: [CustomData(anInt: 0, aString: "zero", aCGPoint: CGPoint.zero), CustomData(anInt: 1, aString: "one", aCGPoint: CGPoint(x: 1, y: 1)) ]),
SectionOfCustomData(header: "Second section", items: [CustomData(anInt: 2, aString: "two", aCGPoint: CGPoint(x: 2, y: 2)), CustomData(anInt: 3, aString: "three", aCGPoint: CGPoint(x: 3, y: 3)) ])
]
Observable.just(sections)
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
3. dataSource에 대한 기타 메소드도 다음과 같이 구현 가능합니다.
dataSource.titleForHeaderInSection = { dataSource, index in
return dataSource.sectionModels[index].header
}
dataSource.titleForFooterInSection = { dataSource, index in
return dataSource.sectionModels[index].footer
}
dataSource.canEditRowAtIndexPath = { dataSource, indexPath in
return true
}
dataSource.canMoveRowAtIndexPath = { dataSource, indexPath in
return true
}
자세한 사용법은 아래 공식 문서를 참고합니다.
https://github.com/RxSwiftCommunity/RxDataSources
단상
-
간단한 tableView의 경우 Rx를 쓰면 짧은 코드로 구현이 가능해 좋은 것 같다
-
RxDataSource도 좋긴 한데... model 만들고 메서드 구현하고 하면 그렇게 많은 효용이 있는 것 같지는 않다. section이 있는 경우 왠만하면 정석대로 가는 것이 좋을 것 같다.
'RxSwift' 카테고리의 다른 글
RxSwift - bind() 말고 drive()를 써보는건 어때요? (2) | 2020.11.29 |
---|---|
RxSwift - subscribe시 onNext를 명시해줘야 하는 이유 (0) | 2020.10.26 |
RxSwift - Dispose & DisposeBag (0) | 2020.10.01 |
RxSwift - tap으로 addTarget을 대체해보자. (1) | 2020.09.17 |
RxSwift - 버튼 활성화 상태 제어하기 #CombineLatest #Binding (0) | 2020.09.16 |