안녕하세요. Skillist입니다
밤에 글을 작성 중인데, 너무 졸리네요.
빠르게 작성 가보겠습니다.
———————————————————————————————————————————————————
비교적 간단한 기록 화면을 먼저 작성해볼거에요.
여러분들도 가벼운 코드들부터 가는게 좋죠?
14라인 : disposeBag입니다.
15라인 : viewModel입니다.
18라인 : 사용할 tableView입니다.
26라인 : viewDidLoad에서 레이아웃 설정을 진행합니다.
33라인 : viewWillAppear에서 history 리스트를 업데이트 합니다. accept를 통해 이벤트를 전달합니다.
RxViewController을 사용하면 되는데, 따로 사용하진 않았습니다. 나중에 기회되면 사용해볼게요.
https://github.com/devxoul/RxViewController
41라인 : viewModel을 바인딩합니다.
45라인 : viewModel의 history List로 tableView를 구성합니다. 제일 간단한 방법이에요.
간단하죠? viewModel의 목록을 드라이브하여, cell을 설정합니다.
57라인 : 화면에 대한 기본 값을 설정합니다.
62라인 : SnapKit을 통해 레이아웃을 구성합니다.
HistoryView는 TabBarController에서 초기화 후에 viewModel을 바인딩 합니다.
———————————————————————————————————————————————————
HistoryViewModel을 함께 보죠.
view -> viewModel로 전달되는것과
viewModel -> view로 전달되는것을 구분했어요.
13라인 : viewWillAppear 시 이벤트를 전달받습니다. publishRelay는 옵저버블이며 옵저버죠. 또, error나 completed로 종료되지 않고 next 이벤트만 방출합니다.
16라인 : view의 TableView에서 사용할 CellData입니다.
19라인 : 결국 viewWillAppear에 이벤트가 전달되면, 20라인의 map을 통해 UserDefaults에서 history 목록을 받아오고 방출합니다.
HistoryView의 tableView가 cellData를 Drive했으니, tableview로 전달됩니다.
이해되시나요??
HistoryView에서 viewWillAppear가 되면, viewModel로 이벤트가 전달되고, history 목록을 방출합니다. 이를 HistoryView의 tableView에서 drive합니다.
이해가 안된다면, 흐름을 생각해보면 됩니다.
———————————————————————————————————————————————————
HistoryModel입니다.
Codable은 인코딩, 디코딩을 위해서 채택했고,
Equatable과 IdentifiableType은 보관함 VC에서 사용할 RxDataSource를 위해 채택했어요.
16라인 : 번역할 언어 입니다.
17라인 : 번역된 언어 입니다.
18라인 : 번역할 text입니다.
19라인 : 번역된 text입니다.
———————————————————————————————————————————————————
Language도 살펴봐야겠죠?
enum으로 구현했습니다.
한국어, 영어, 일본어, 중국어 4가지만 사용했습니다.
———————————————————————————————————————————————————
localize도 궁금하시죠???
계속 꼬리에 꼬리를 물어서 다른 코드도 보여주게 되네요. 꼬꼬무
단순합니다. String을 extension했습니다.
컴퓨티드 프로퍼티입니다.
로컬라이즈 text를 반환합니다.
———————————————————————————————————————————————————
UserDefault도 볼까요?
UserDefault를 사용하기 쉽게 extension했습니다.
12라인 : history에 대한 key 입니다.
17라인 : history에 대한 get 입니다. data를 가져와, HistoryModel로 디코딩 합니다. 실패 하면, 빈 array로 반환합니다.
24라인 : history에 대한 set 입니다. 최대 10개까지 가질수 있습니다.
33라인 : history를 추가합니다. 중복 제거 로직이에요.
35라인 : 같은 history가 이미 존재할 경우, 기존 기록을 삭제합니다.
39라인 : 가장 최근의 기록이 제일 위로 올라올 수 있도록, 저장합니다.
———————————————————————————————————————————————————
RxSwift에 대한 설명은 거의 없었어요.
그래도 다른 코드를 많이 소개하여, 어지러울 수 있는데, 한번 차근차근 보면 이해될거에요.
어려운 코드는 아니에요.
너무 졸려서 자야겠네요. 고생하셨어요~
잘못되거나 부족한 내용 등, 피드백 감사합니다!
https://github.com/DeveloperSkillist/TranstorKing
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 전체 코드 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
import UIKit
import RxSwift
import RxCocoa
import SnapKit
class HistoryView: UIViewController {
let disposeBag = DisposeBag()
var viewModel: HistoryViewModel? //viewModel입니다.
//tableView
private var tableView: UITableView = {
var tableView = UITableView()
tableView.backgroundColor = .secondarySystemBackground
tableView.separatorStyle = .none
tableView.register(HistoryTableViewCell.self, forCellReuseIdentifier: HistoryTableViewCell.identify)
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
attribute()
layout()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//viewWillAppear에서 history를 새로고침
self.viewModel?.viewWillAppear
.accept(())
}
func bind(_ viewModel: HistoryViewModel) {
self.viewModel = viewModel
//기본적인 cellData를 통해, tableView 구성
viewModel.cellData
.drive(tableView.rx.items) { tableView, row, data in
guard let cell = tableView.dequeueReusableCell(withIdentifier: HistoryTableViewCell.identify) as? HistoryTableViewCell else {
return UITableViewCell()
}
cell.selectionStyle = .none //selection 애니메이션 삭제
cell.setup(historyModel: data) //cell data 설정
return cell
}
.disposed(by: disposeBag)
}
private func attribute() {
view.backgroundColor = .secondarySystemBackground
navigationItem.title = "history_title".localize
}
private func layout() {
view.addSubview(tableView)
tableView.snp.makeConstraints {
$0.edges.equalToSuperview()
}
}
}
import RxSwift
import RxCocoa
struct HistoryViewModel {
let disposeBag = DisposeBag()
//view -> viewModel
let viewWillAppear = PublishRelay<Void>()
//viewModel -> view
let cellData: Driver<[HistoryModel]>
init() {
cellData = viewWillAppear
.map {
UserDefaults.standard.history
}
.asDriver(onErrorJustReturn: [])
}
}
import Foundation
enum Language: String, CaseIterable, Codable {
case ko
case en
case ja
case ch = "zh-CN"
var title: String {
switch self {
case .ko:
return "Korean".localize
case .en:
return "English".localize
case .ja:
return "Japanese".localize
case .ch:
return "Chinese".localize
}
}
}
extension String {
var localize: String {
NSLocalizedString(self, comment: self)
}
}
extension UserDefaults {
var historyKey: String {
return "history"
}
var history: [HistoryModel] {
get {
guard let data = UserDefaults.standard.data(forKey: historyKey) else {
return []
}
return (try? PropertyListDecoder().decode([HistoryModel].self, from: data)) ?? []
}
set {
var newHistorys = newValue
if newHistorys.count > 10 {
newHistorys.removeLast()
}
UserDefaults.standard.setValue(try? PropertyListEncoder().encode(newHistorys), forKey: historyKey)
}
}
func addHistory(historyModel: HistoryModel) {
var histories = UserDefaults.standard.history
if let index = histories.firstIndex(of: historyModel) {
histories.remove(at: index)
}
self.history = [historyModel] + histories
}
}
'iOS 개발 > 번역기 앱(RxSwift)' 카테고리의 다른 글
번역기 앱 - 6. 보관함 화면 Cell 구현 (0) | 2022.02.01 |
---|---|
번역기 앱 - 5. 보관함 화면 구현 (0) | 2022.02.01 |
번역기 앱 - 4. 기록화면의 cell 구현 (0) | 2022.02.01 |
번역기 앱 - 2. 기본 구현 (0) | 2022.01.31 |
번역기 앱 - 1. 시작하기 (0) | 2022.01.31 |