[swift] RxDataSources를 사용한 위치 정보 처리 방법

이번 포스트에서는 Swift에서 RxDataSources를 사용하여 위치 정보를 처리하는 방법에 대해 알아보겠습니다.

RxDataSources란?

RxDataSources는 RxSwift에서 제공하는 라이브러리로, UITableViewDataSource와 UICollectionViewDataSource의 구현을 단순화해주고, 데이터 소스를 쉽게 바인딩할 수 있는 기능을 제공합니다.

위치 정보 처리를 위한 라이브러리 설치

먼저, 위치 정보를 처리하기 위해 CoreLocation 라이브러리를 설치해야 합니다. Podfile에 다음과 같이 추가합니다.

pod 'RxDataSources'

그리고 터미널에서 pod install 명령어를 실행하여 라이브러리를 설치합니다.

위치 정보 가져오기

위치 정보를 가져오기 위해서는 CoreLocation을 사용해야 합니다.

import CoreLocation
import RxSwift
import RxCocoa

class LocationService: NSObject, CLLocationManagerDelegate {
    private let locationManager = CLLocationManager()
    private let disposeBag = DisposeBag()
    
    let location: Observable<CLLocationCoordinate2D>
    let authorizationStatus: Observable<CLAuthorizationStatus>
    
    override init() {
        // 위치 정보를 업데이트 받을 때마다 PublishSubject를 통해 새로운 위치 정보를 방출합니다.
        let locationSubject = PublishSubject<CLLocationCoordinate2D>()
        self.location = locationSubject.asObservable()
        
        // 권한 상태를 업데이트 받을 때마다 PublishSubject를 통해 새로운 상태를 방출합니다.
        let authorizationStatusSubject = PublishSubject<CLAuthorizationStatus>()
        self.authorizationStatus = authorizationStatusSubject.asObservable()
        
        super.init()
        
        locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()
        
        // 위치 정보 업데이트 설정
        locationManager.rx
            .didUpdateLocations
            .map { $0.first?.coordinate }
            .bind(to: locationSubject)
            .disposed(by: disposeBag)
        
        // 권한 상태 변경 처리
        locationManager.rx
            .didChangeAuthorizationStatus
            .bind(to: authorizationStatusSubject)
            .disposed(by: disposeBag)
    }
    
    // 위치 가져오기 시작
    func startUpdatingLocation() {
        locationManager.startUpdatingLocation()
    }
    
    // 위치 가져오기 중지
    func stopUpdatingLocation() {
        locationManager.stopUpdatingLocation()
    }
    
    // 권한 상태 체크
    func checkAuthorizationStatus() {
        let status = CLLocationManager.authorizationStatus()
        authorizationStatusSubject.onNext(status)
    }
}

위의 코드는 RxSwift를 사용하여 CoreLocation을 더 간편하게 사용하기 위한 LocationService 클래스입니다.

데이터 소스 바인딩

RxDataSources를 사용하여 위치 정보를 UITableView에 바인딩하는 예제를 살펴보겠습니다.

import UIKit
import RxSwift
import RxCocoa
import RxDataSources

class LocationListViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!
    
    let disposeBag = DisposeBag()
    let locationService = LocationService()
    let dataSource = RxTableViewSectionedReloadDataSource<LocationSectionModel>(
        configureCell: { dataSource, tableView, indexPath, item in
            let cell = tableView.dequeueReusableCell(withIdentifier: "LocationCell", for: indexPath)
            cell.textLabel?.text = item.name
            return cell
        }
    )
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 위치 정보 가져오기 시작
        locationService.startUpdatingLocation()
        
        // 위치 정보 바인딩
        locationService.location
            .map { [LocationSectionModel(model: "", items: [$0])] }
            .bind(to: tableView.rx.items(dataSource: dataSource))
            .disposed(by: disposeBag)
        
        // 테이블 뷰 리로드
        locationService.location
            .subscribe(onNext: { [weak self] _ in
                self?.tableView.reloadData()
            })
            .disposed(by: disposeBag)
    }
}

위의 코드에서는 LocationService에서 제공하는 location Observable을 사용하여 위치 정보를 계속해서 업데이트하고, RxDataSources를 사용하여 UITableView에 바인딩합니다.

위치 정보가 업데이트될 때마다 데이터 소스를 업데이트하고, 이를 tableView.rx.items에 바인딩하여 테이블 뷰를 업데이트합니다.

테이블 뷰의 셀은 configureCell 클로저를 통해 구성하며, 이 예제에서는 단순히 위치 이름을 표시하는 셀을 사용하였습니다.

결론

이번 포스트에서는 RxDataSources를 사용하여 위치 정보를 처리하는 방법에 대해 알아보았습니다. RxSwift와 CoreLocation을 함께 사용하여 위치 정보를 효과적으로 다룰 수 있습니다. RxDataSources를 이용하면 UITableView나 UICollectionView의 데이터 소스를 쉽게 관리할 수 있으므로, 복잡한 앱 개발에서 유용하게 사용할 수 있습니다.

참고 자료