apple/UIKit & ReactiveX

iOS RxSwift 06 | RxDataSources 기초

lgvv 2021. 8. 19. 15:30

✅ 여기 포스팅은 이전 포스팅에서 SnapKit을 적용한 후에 여기로 넘어왔다.

이거 정말 극한으로 어렵다 ㅠㅠ ...

뭔가 알듯말듯 하면서도 잘 이해가 안가.

공식문서를 뚜드려보는 중인데 왜이렇게 어렵지 ㅠㅠㅠㅠㅠㅠㅠㅠㅠ

🟠 이번 시간에는 커스텀 셀을 적용하지 않고서 RxDataSources를 활용해보자 

그리고 다음시간에 커스텀 셀을 붙여보자.

 

✅ 이전 포스팅을 확인하려면...

2021.08.19 - [iOS/SnapKit] - iOS SnapKit 05 | iOS tableView를 코드로 구성하는 법 03

 

iOS SnapKit 05 | iOS tableView를 코드로 구성하는 법 03

✅ 이번 시간에는 RxSwift를 적용하여 코드를 조금 더 수정해보자 코드로 테이블 뷰를 구성하는게 처음이다보니 계속 늘어지는 기분이지만 꾸준히 나아가보자! // // ViewController05.swift // SnapKit_practi

rldd.tistory.com

 

✅ 목차 

1. pod 설치하기

2. MySection 만들기 - import RxDataSources

 

 

✅ RxSwift에서 RxDataSource를 사용하려면...

우선 pod을 설치해야 한다.

pod 'RxDataSources'

아... pod을 설치해야 함을 몰라서 이걸 혼자서 이런 저런거 다 찾아본거 생각하니.. ㅜ 

 

✅ 2. MySection 만들기 - import RxDataSources

struct MySection {
    var header : String
    var items: [Item]
}

extension MySection : AnimatableSectionModelType {
    init(original: MySection, items: [Int]) {
        self = original
        self.items = items
    }
    
    var identity: String {
        return header
    }
    // 셀에 들어갈 데이터 타입을 정해야 한다.
    typealias Item = Int
    
}

⭐️ 여기 코드가 커스텀 Cell을 담당하는 부분인데 난 잘 이해가 안가요 ^_^ ⭐️

 -> 다음 포스팅이나 다다음 포스팅에서 알게되겠죠? 

 

여기 코드를 보면 상당히 복잡하다.

차근차근 알아보자면 쉽게 말해서 Cell의 타입을 정의하는 것이 MySection 부분이다.

셀의 애니메이션을 위해 AnimatableSectionModelType 모델을 상속받아 사용한다.

상속을 받으면 Identity와 Item을 정의해야 에러가 나지 않는데, 내가 작성한 코드를 그대로 작성하면 된다.

 

❗️Item은 테이블 안에 들어갈 데이터의 타입으로 우리가 정한 타입이 있다면 우리가 정한 타입으로 한다.

identity는 연산 프로퍼티로 바꾸었다.

 

MySection타입 객체 하나가 테이블 뷰에서 섹션 하나하나가 될 예정이다.

header는 섹션의 title과 비슷한 역할, items는 섹션의 row와 비슷한 역할을 한다.

 

🟠 이렇게 해주면 RxDataSoure를 사용하기 위한 기본 세팅은 마쳤다.

 

✅ 전체 코드 리뷰

//
//  ViewController05.swift
//  SnapKit_practice
//
//  Created by Hamlit Jason on 2021/08/19.
//

import Foundation
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
import Then

class ViewController06 : UIViewController {
    
    let data = Observable<[String]>.just(["first","second","third",])
    
    let tableView = UITableView().then {
        $0.translatesAutoresizingMaskIntoConstraints = false
        $0.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    }
    
    let updateButton = UIButton().then {
        $0.setTitle("버튼클릭해봐", for: .normal)
    }
    
    let disposeBag = DisposeBag()
    var dataSource: RxTableViewSectionedAnimatedDataSource<MySection>?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemTeal
        addSubView()
        setLayout()
        
        //        _ = data.bind(to: tableView.rx.items(cellIdentifier: ViewController06Cell.identifier, cellType: ViewController06Cell.self)) { index, item, cell in
        //            print("cell")
        //            cell.img.image = UIImage(systemName: "ticket")
        //            cell.label.text = "view 6 item \(index)"
        //        }.disposed(by: disposeBag)
        
        let dataSource = RxTableViewSectionedAnimatedDataSource<MySection>(
            configureCell: { ds, tv, _, item in
                let cell = tv.dequeueReusableCell(withIdentifier: "Cell") ?? UITableViewCell(style: .default, reuseIdentifier: "Cell")
                cell.textLabel?.text = "Item \(item)"
                
                return cell
            },
            titleForHeaderInSection: { ds, index in
                return ds.sectionModels[index].header
            }
        )
        
        self.dataSource = dataSource
        
        let sections = [
            MySection(header: "First section", items: [
                1,
                2
            ]),
            MySection(header: "Second section", items: [
                3,
                4
            ])
        ]
        
        Observable.just(sections)
            .bind(to: tableView.rx.items(dataSource: dataSource))
            .disposed(by: disposeBag)
        
        tableView.rx.setDelegate(self)
            .disposed(by: disposeBag)
        
    } // viewDidLosad
}

extension ViewController06 : UITableViewDelegate {
    func setLayout() {
        tableView.snp.makeConstraints {
            $0.top.equalTo(0)
            $0.leading.equalTo(0)
            $0.trailing.equalTo(0)
            $0.bottom.equalTo(-200)
            //            $0.edges.equalTo(view)
            //                .inset(UIEdgeInsets(top: 0, left: 0, bottom: 200, right: 0))
        }
    }
    func addSubView() {
        view.addSubview(tableView)
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        guard let item = dataSource?[indexPath],
              // .. or section and customize what you like
              dataSource?[indexPath.section] != nil
        else {
            return 0.0
        }
        
        print("\(item) : height")
        return CGFloat(40 + item * 10)
    }
}


struct MySection {
    var header: String
    var items: [Item]
}

extension MySection : AnimatableSectionModelType {
    typealias Item = Int
    
    var identity: String {
        return header
    }
    
    init(original: MySection, items: [Item]) {
        self = original
        self.items = items
    }
}

 

 

코드에 대한 결과