[swift] RxDataSources를 사용한 뷰 컨트롤러 간 데이터 전달 방법

이번 글에서는 Swift에서 RxDataSources를 사용하여 뷰 컨트롤러간 데이터를 전달하는 방법에 대해 알아보겠습니다. RxDataSources는 RxSwift와 함께 사용되는 라이브러리로, 테이블 뷰나 컬렉션 뷰의 데이터소스를 간편하게 구현할 수 있도록 도와줍니다.

1. RxDataSources 설치하기

먼저 RxDataSources를 설치해야 합니다. Cocoapods를 사용한다면 Podfile에 다음과 같은 코드를 추가합니다.

pod 'RxDataSources'

설치 후에는 프로젝트를 다시 빌드해야 합니다.

2. 데이터 구조 정의하기

데이터를 전달하기 위해서는 데이터 모델을 먼저 정의해야 합니다. 예를 들어, 사용자 정보를 담는 User 모델을 정의해보겠습니다.

struct User {
    let name: String
    let age: Int
}

3. 데이터 전달하는 뷰컨트롤러 만들기

데이터를 전달하는 뷰 컨트롤러에서는 RxDataSources를 사용하여 데이터를 구성합니다. 예를 들어, User 모델의 배열을 사용하여 테이블 뷰를 구성하고 데이터를 전달하는 방법을 알아보겠습니다.

import RxSwift
import RxCocoa
import RxDataSources

class UserListViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!
    
    let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let users = [
            User(name: "John", age: 25),
            User(name: "Lisa", age: 30),
            User(name: "David", age: 28)
        ]
        
        let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, User>>(
            configureCell: { dataSource, tableView, indexPath, user in
                let cell = tableView.dequeueReusableCell(withIdentifier: "UserCell", for: indexPath)
                cell.textLabel?.text = user.name
                cell.detailTextLabel?.text = "\(user.age) years old"
                return cell
            })
        
        Observable.just([SectionModel(model: "User", items: users)])
            .bind(to: tableView.rx.items(dataSource: dataSource))
            .disposed(by: disposeBag)
    }
}

위 코드에서는 User 모델의 배열을 사용하여 섹션을 “User”로 설정하고, 각 사용자를 아이템으로 사용하여 데이터를 구성합니다. 그리고 RxTableViewSectionedReloadDataSource를 사용하여 테이블 셀을 구성하고, 데이터를 바인딩합니다.

4. 데이터 전달 받는 뷰 컨트롤러 만들기

데이터를 전달 받는 뷰 컨트롤러에서는 데이터를 수신받을 수 있는 Observable을 선언하고, 데이터를 처리하는 로직을 작성합니다.

import RxSwift
import RxCocoa

class UserDetailsViewController: UIViewController {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var ageLabel: UILabel!
    
    let disposeBag = DisposeBag()
    
    var user: User?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        if let user = user {
            nameLabel.text = user.name
            ageLabel.text = "\(user.age) years old"
        }
    }
}

위 코드에서는 User 모델에 맞게 이름과 나이를 표시하기 위해 nameLabel과 ageLabel을 설정합니다.

5. 데이터 전달하기

데이터를 전달하는 뷰 컨트롤러에서는 사용자가 아이템을 선택했을 때, 해당 사용자 데이터를 전달하는 로직을 작성합니다.

import RxSwift
import RxCocoa

class UserListViewController: UIViewController {
    // ...
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.rx.modelSelected(User.self)
            .subscribe(onNext: { [weak self] user in
                guard let self = self else { return }
                let userDetailsVC = self.storyboard?.instantiateViewController(withIdentifier: "UserDetailsViewController") as! UserDetailsViewController
                userDetailsVC.user = user
                self.navigationController?.pushViewController(userDetailsVC, animated: true)
            })
            .disposed(by: disposeBag)
    }
}

위 코드에서는 RxTableView의 modelSelected 이벤트를 구독하여 사용자가 아이템을 선택했을 때를 처리합니다. 선택된 사용자를 User 객체로 받아온 후 UserDetailsViewController로 전환하여 사용자 데이터를 전달합니다.

이제 RxDataSources를 사용하여 뷰 컨트롤러간에 데이터를 간단하게 전달하는 방법을 알아보았습니다. RxDataSources의 강력한 기능을 활용하면 데이터 관리 및 전달을 효과적으로 처리할 수 있습니다.

참고자료: