ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

728x90
๋ฐ˜์‘ํ˜•

๋ณธ ํฌ์ŠคํŒ…์€ ๊ณฐํŠ€๊น€๋‹˜์˜ ๊ฐ•์˜์˜์ƒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ, ๊ฐœ์ธ์ ์œผ๋กœ ๊ณต๋ถ€ํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

๋”์šฑ ์ž์„ธํ•œ ๋‚ด์šฉ์€, ๊ฐ•์˜ ์˜์ƒ์„ ์ง์ ‘ ์‹œ์ฒญํ•˜์‹œ๋Š”๊ฒƒ์„ ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค! 

 

 

 

์ด์ „์— ํฌ์ŠคํŒ…ํ•œ RxSwift + MVVMํŒจํ„ด [Subject๋ฅผ ํ™œ์šฉํ•ด๋ณด์ž]์— ์ด์–ด์ง€๋Š” ํฌ์ŠคํŒ… ์ž…๋‹ˆ๋‹ค.

 

 


์ €๋ฒˆ ํฌ์ŠคํŒ… ๋ง๋ฏธ์— ๋‚˜์™”๋˜ RxCocoa์— ๋Œ€ํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

RxCocoa๋ฅผ ์š”์•ฝํ•˜์ž๋ฉด,

[RxSwift์˜ ์š”์†Œ๋“ค์„  UIKit์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก extension ์‹œ์ผœ์„œ ์ ‘๋ชฉ์‹œํ‚จ ๊ฒƒ]

์ด๋ผ๊ณ  ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ธ€๋กœ๋งŒ ๋ณด๋ฉด ์‰ฝ๊ฒŒ ์ดํ•ด๊ฐ€ ๋˜์ง€ ์•Š์œผ๋‹ˆ, ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

override func viewDidLoad() {
        super.viewDidLoad()
        
        viewModel.itemsCount
            .subscribe(onNext: {self.itemCountLabel.text = "\($0)"})
            .disposed(by: disposeBag)
            
                                    .
                                    .
                                    .
}

ํ˜„์žฌ๋Š” ์ด๋ ‡๊ฒŒ ์ฝ”๋“œ๊ฐ€ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค.

viewModel์˜ itemsCount๋ฅผ ๊ตฌ๋…ํ•˜๋ฉด์„œ, PublishSubject<Int>๊ฐ’์„ itemCountLabel.text์— ๋„˜๊ฒจ์ฃผ๊ณ  ์žˆ์ฃ ?? 

 

์ด ์ฝ”๋“œ๋ฅผ ํ•œ๋ฒˆ ์ด๋ ‡๊ฒŒ ๋ฐ”๊ฟ”๋ณผ๊นŒ์š”?

override func viewDidLoad() {
        super.viewDidLoad()
        
        viewModel.itemsCount
            .map{"\($0)"}
            .bind(to: itemCountLabel.rx.text)
            .disposed(by: disposeBag)
            
                                    .
                                    .
                                    .
}

์–ด๋–ค์ ์ด ๋‹ฌ๋ผ์กŒ๋Š”์ง€ ์•„์‹œ๊ฒ ๋‚˜์š”??

๋ฐ”๋กœ .subscribe()๋ฅผ ํ†ตํ•ด text์— ๊ฐ’์„ ์ „๋‹ฌ ํ•ด ์ฃผ์—ˆ๋˜ ๋ถ€๋ถ„์ด

-> .bind()๋ผ๋Š” operator๋ฅผ ํ†ตํ•ด์„œ itemCountLabel์— ์ง์ ‘ ๊ฐ’์„ ์ง‘์–ด๋„ฃ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค!

(.map()์ด ์ƒˆ๋กœ ์ƒ๊ธด ์ด์œ ๋Š”, text์— ๊ฐ’์„ ์ง์ ‘ binding์‹œ์ผœ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด์ „์— ๋ฏธ๋ฆฌ Stringํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ž‘์—…์„ ์ถ”๊ฐ€ ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.)

 

์ฆ‰, .bind()๋ผ๋Š” operator๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, UIKit์˜ ์ปดํฌ๋„ŒํŠธ์— ์ง์ ‘ ๊ฐ’์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” 

.rx๋ผ๋Š” ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•˜๊ณ  ์ด๊ฒƒ์„ RxCocoa์—์„œ ์ œ๊ณตํ•ด์ค๋‹ˆ๋‹ค!

 

์‚ฌ์‹ค .rx๋ฅผ ์จ์•ผํ•œ๋‹ค๊ธฐ ๋ณด๋‹ค๋Š” binder<T> ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” extension์ด ํ•„์š” ํ•œ ๊ฒƒ์ด์ง€๋งŒ,

RxCocoa๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ๋Š” .rx ๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ๋Œ€๋ถ€๋ถ„ ์ง€์›ํ•ด์ฃผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

(ํ•˜์ง€๋งŒ, ๋Œ€๋ถ€๋ถ„ ์ด๋ผ๊ณ  ์ ์€ ๊ฒƒ์€ ๋‹น์—ฐํžˆ ๊ฐœ๋ฐœ์ž๊ฐ€ ํ•„์š”ํ•œ ์ •๋„์— ๋”ฐ๋ผ์„œ๋Š” ์ƒˆ๋กœ extension์„ ๋งŒ๋“ค์–ด์ค˜์•ผ ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค!)

 

๋˜ํ•œ, .bind()๋ฅผ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ์ง€๋งŒ ์ˆœํ™˜์ฐธ์กฐ๋ฅผ ์•Œ์•„์„œ ์ฒ˜๋ฆฌ ํ•ด ์ค€๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ์ตœ์ข…์ ์œผ๋กœ, Observable์„ UIKit์— ๋ฐ”์ธ๋”ฉ ํ•ด์ฃผ๋Š” ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค!

override func viewDidLoad() {
        super.viewDidLoad()
        
        viewModel.itemsCount
            .map{"\($0)"}
            .bind(to: itemCountLabel.rx.text)
            .disposed(by: disposeBag)
        viewModel.totalPrice
            .map{$0.currencyKR()}
            .bind(to: totalPrice.rx.text)
            .disposed(by: disposeBag)
    }

๊ทธ๋Ÿฐ๋ฐ ๋งŒ์•ฝ, data์ฒ˜๋ฆฌ๊ฐ€ main thread๊ฐ€ ์•„๋‹Œ global thread์—์„œ ์ฒ˜๋ฆฌ๊ฐ€ ๋œ๋‹ค๋ฉด,  ์œ„์˜ ์ฝ”๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๊ฐ€ ๋ ๊นŒ์š”???

 

์‚ฌ์‹ค iOS์˜ ๊ธฐ๋ณธ์ ์ธ ๋™์ž‘ thread๋Š” main thread๋กœ ์ง€์ •์ด ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, ๋ฐ˜๋“œ์‹œ ๋ชจ๋“  ์ฒ˜๋ฆฌ๊ฐ€ main์—์„œ ์ฒ˜๋ฆฌ๊ฐ€ ๋œ๋‹ค๋Š” ๋ณด์žฅ์„ ํ•  ์ˆ˜ ์—†๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์ž„์˜๋กœ ๋ณ€๊ฒฝํ•ด ๋ฒ„๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์—, ์šฐ๋ฆฌ๋Š” ์œ„ ์ฝ”๋“œ์— ์ด์ „์— ์•Œ์•„๋ณด์•˜๋˜ observeOn()์ด๋ผ๋Š” operator๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ 

์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌ์„ฑํ•˜๋ฉด, ํ•ด๋‹น ์ฝ”๋“œ์˜ ๋™์ž‘์„ ๊ฐ•์ œ๋กœ main์“ฐ๋ ˆ๋“œ๋กœ ๋ถ„๊ธฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!!

 override func viewDidLoad() {
        super.viewDidLoad()
        
        viewModel.itemsCount
            .map{"\($0)"}
            .observeOn(MainScheduler.instance)
            .bind(to: itemCountLabel.rx.text)
            .disposed(by: disposeBag)
        viewModel.totalPrice
            .map{$0.currencyKR()}
            .observeOn(MainScheduler.instance)
            .bind(to: totalPrice.rx.text)
            .disposed(by: disposeBag)
    }

 

 

 

์ž, ๊ทธ๋ ‡๋‹ค๋ฉด ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์šฐ๋ฆฌ๊ฐ€ ์ด๋ฒˆ์— ํ•˜๊ณ ์žํ–ˆ๋˜ menusObservable์„ UITableView์— ๋ฐ”์ธ๋”ฉ ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์œ„์—์„œ์™€ ๋™์ผํ•˜๊ฒŒ .rx๋ฅผ ์‚ฌ์šฉํ• ํ…๋ฐ, ์šฐ์„  ์ฝ”๋“œ๋ฅผ ๋ณด๊ณ  ์„ค๋ช…ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

let cellID = "MenuItemTableViewCell"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        
        viewModel.menusObservable
            .bind(to: tableView.rx.items(cellIdentifier: cellID, 
            cellType: MenuItemTableViewCell.self)){index, item, cell in
                cell.title.text = item.name
                cell.price.text = "\(item.price)"
                cell.count.text = "\(item.count)"
            }
            .disposed(by: disposeBag)
    }

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด, ์—ญ์‹œ๋‚˜ .bind๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  tableview.rx๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ๊นŒ์ง€๋Š” ์ด์ „๊ณผ ๋™์ผํ•˜์ฃ ? ๋‹ค์Œ๋„ ํฌ๊ฒŒ ์–ด๋ ต์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ดํ›„์—๋Š” .items(cellIdentifier: , cellType: )๋ฅผ ํ˜ธ์ถœํ•˜๋Š”๋ฐ, ์ด ํ•จ์ˆ˜๋Š” @escaping closer๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

(cellIdentifier์—๋Š” cell์˜ ID๋ฅผ ์ž…๋ ฅ ํ•ด ์ฃผ๊ณ , cellType์—๋Š” ๋ง ๊ทธ๋Œ€๋กœ ํ•ด๋‹น cell์˜ ํƒ€์ž…์„ ์ž‘์„ฑํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.)

 

์ด๋ฅผ ํ†ตํ•ด์„œ @escaping closer์—๋Š” index, item, cell์ด ์ธ์ž๋กœ ๋“ค์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๊ฐ ์ธ์ž๋“ค์€ 

1) index : IndexPath.row์™€ ๊ฐ™์€ ์—ญํ• 

2) item : tableview์— ๋„ฃ์–ด์ฃผ๋Š” ์‹ค์ œ ๋ฐ์ดํ„ฐ(์ •ํ™•ํ•˜๊ฒŒ๋Š” Sequence์˜ Element!).

(์œ„์˜ ์˜ˆ์‹œ์—์„œ๋Š” [Menu]์˜ index๋ณ„ Element๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค!)

3) cell : tableview์—์„œ index๋ณ„๋กœ ๊ทธ๋ ค์ค„ cell์˜ ์ •๋ณด

๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค!

 

์ž ๊ทธ๋Ÿผ ์ด๋Œ€๋กœ ์‹คํ–‰์„ ์‹œํ‚ค๋ฉด ์ž˜ ๋™์ž‘์„ ํ• ๊นŒ์š”???

.

.

.

์ •๋‹ต์€ "๊ทธ๋ ‡์ง€ ์•Š๋‹ค!" ์ž…๋‹ˆ๋‹ค.

 

๊ทธ ์ด์œ ์— ๋Œ€ํ•ด์„œ๋Š” ์กฐ๊ธˆ ์ƒ๊ฐ์„ ํ•ด ๋ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ํ˜„์žฌ PublishSubjectํƒ€์ž…์œผ๋กœ ์ƒ์„ฑ์ด ๋œ menusObservable์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฐ๋ฐ Subject์˜ ํฐ ํŠน์ง• ์ค‘ ํ•˜๋‚˜๊ฐ€, ์ƒ์„ฑ๊ณผ ๋™์‹œ์— Observable์„ ๋ฐฉ์ถœํ•˜๊ธฐ ์‹œ์ž‘ํ•œ๋‹ค ๋ผ๋Š” ์  ์ž…๋‹ˆ๋‹ค.

์•„๋ž˜์˜ ๋งˆ๋ธ”๊ทธ๋ฆผ์„ ํ•œ๋ฒˆ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ฒซ๋ฒˆ์งธ stream์€ .subscribe()์‹œ์  ์ดํ›„์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์˜ค๋ฏ€๋กœ ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์ง€๋งŒ / ๋‘๋ฒˆ์งธ stream์€ .subscribe์‹œ์  ์ดํ›„์— ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Œ

์ด ์‚ฌ์ง„์—์„œ ๋งจ์œ„์˜ [Red] [Green] ๋ฐ์ดํ„ฐ๋Š” ์ด๋ฏธ Observable๋กœ ๋ฐฉ์ถœ์ด ๋˜๊ณ  ์žˆ๋Š” ๋ชจ์Šต์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ๊ฐ€์žฅ ์•„๋ž˜์—์„œ .subscribe()๋ฅผ ํ•œ ์‹œ์ ์—์„œ๋Š” ์ด์ „ data์—๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์•Œ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด PublishSubject๋ฅผ 

.subscribe()ํ•œ๋‹ค๊ณ  ํ•ด๋„ ์•„๋ฌด๋Ÿฐ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๊ฒŒ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

(์ฐธ๊ณ ๋กœ, ์•„๋ž˜์—์„œ ๋‘๋ฒˆ์งธ stream๊ณผ ๊ฐ€์žฅ ์•„๋ž˜์˜ stream์€ ์•„์˜ˆ ๋ณ„๋„์˜ stream ์ด๋ผ๋Š” ์ ์„ ์žŠ์œผ์‹œ๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค!!!)

 

๊ทธ๋Ÿฐ๋ฐ ์šฐ๋ฆฌ๊ฐ€ ์ž‘์„ฑํ•œ ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด,

class MenuViewController: UIViewController {
    let viewModel = MenuListViewModel()
    let disposeBag = DisposeBag()
    let cellID = "MenuItemTableViewCell"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        viewModel.menusObservable
            .bind(to: tableView.rx.items(cellIdentifier: cellID,
            cellType: MenuItemTableViewCell.self)){index, item, cell in
                cell.title.text = item.name
                cell.price.text = "\(item.price)"
                cell.count.text = "\(item.count)"
            }
            .disposed(by: disposeBag)
    }
                                    .
                                    .
                                    .
}
    
 class MenuListViewModel{    
    var menusObservable = PublishSubject<[Menu]>()
    init(){
        var menus : [Menu] = [
            Menu(name: "ํŠ€๊น€1", price: 100, count: 0),
            Menu(name: "ํŠ€๊น€1", price: 100, count: 0),
            Menu(name: "ํŠ€๊น€1", price: 100, count: 0),
            Menu(name: "ํŠ€๊น€1", price: 100, count: 0)
        ]
        menusObservable.onNext(menus)
    }
}

viewModel์ด๋ผ๋Š” ๋ณ€์ˆ˜๊ฐ€ ์ƒ์„ฑ์ด ๋˜๋Š” ๋™์‹œ์— init()ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ดˆ๊ธฐํ™”๋ฅผ ์ง„ํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ด ์ดˆ๊ธฐํ™” ๊ณผ์ •์—์„œ menusObservable์—์„œ menus๋ฅผ ๋ณด๋‚ด๋Š”๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ฆ‰,

์šฐ๋ฆฌ๊ฐ€ menusObservable์„ ๋ฐ”์ธ๋”ฉํ•˜์—ฌ tableView์—์„œ ํ•ด๋‹น item์„ ๊ด€์ฐฐ ํ•˜๋Š” ์‹œ์ ๋ณด๋‹ค

๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐ„ ์‹œ์ ์ด ์•ž์„œ๊ธฐ ๋•Œ๋ฌธ์—, PublishSubject์˜ ํŠน์„ฑ ์ƒ .subscribe()์ด์ „ ๋ฐ์ดํ„ฐ๋ฅผ ์•Œ ๋ฐฉ๋ฒ•์ด ์—†๋Š” ๊ฒƒ

์ž…๋‹ˆ๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋ฌธ์ œ๋Š” ์•Œ์•˜์œผ๋‹ˆ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•๋„ ์žˆ๊ฒ ์ฃ ?

๋ฐ”๋กœ ์ง์ „ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜๋งŒ ์žˆ๋‹ค๋ฉด ์ฝ”๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•  ๊ฒƒ ์ž…๋‹ˆ๋‹ค!

๊ทธ๋ฆฌ๊ณ  ์ด ๊ธฐ๋Šฅ์„ ํ•˜๋Š” Subject๋„ ์šฐ๋ฆฌ๋Š” ์ด๋ฏธ BehaviorSubject๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

(ํ˜น์‹œ, Subject์˜ ์ข…๋ฅ˜์— ๋Œ€ํ•ด ์ž˜ ๋ชจ๋ฅด์‹œ๋Š” ๋ถ„์€ ์ด ๊ฒŒ์‹œ๋ฌผ์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”!)

 

๋”ฐ๋ผ์„œ, ์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด MenuListViewModel ํด๋ž˜์Šค์—์„œ menusObservable์„ ์„ ์–ธ ํ•  ๋•Œ, BehaviorSubject๋กœ ์ƒ์„ฑํ•ด์ค€๋‹ค๋ฉด 

.subscribe()ํ•˜๊ธฐ ์ง์ „ ๊ฐ’์ธ, menus๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค!

class MenuListViewModel{
    
    var menusObservable = BehaviorSubject<[Menu]>(value: [])
    
    lazy var itemsCount = menusObservable
        .map{$0.map{$0.count}.reduce(0,+)}
    lazy var totalPrice = menusObservable
        .map{$0.map{$0.price * $0.count}.reduce(0,+)}
    
    init(){
        var menus : [Menu] = [
            Menu(name: "ํŠ€๊น€1", price: 100, count: 0),
            Menu(name: "ํŠ€๊น€1", price: 100, count: 0),
            Menu(name: "ํŠ€๊น€1", price: 100, count: 0),
            Menu(name: "ํŠ€๊น€1", price: 100, count: 0)
        ]
        menusObservable.onNext(menus)
    }
    
}

 

๊ทธ๋ ‡๋‹ค๋ฉด ์ •๋ง Binding์ด ์ „๋ถ€ ์ž˜ ๋˜์–ด์žˆ๋Š”์ง€,

ORDER๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๊ฐ’์ด ๋ณ€ํ•˜๊ฒŒํ•˜์—ฌ ๋™์ž‘ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

@IBAction func onOrder(_ sender: UIButton) {
        // TODO: no selection
        // showAlert("Order Fail", "No Orders")
        // performSegue(withIdentifier: "OrderViewController", sender: nil)
        
        viewModel.menusObservable
            .onNext([Menu(name: "์šฉ์ธ", price: 1000, count: Int.random(in: 0...4)),
                     Menu(name: "์šฉ์ธ", price: 1000, count: Int.random(in: 0...4)),
                     Menu(name: "์šฉ์ธ", price: 1000, count: Int.random(in: 0...4))
            ])
        
    }

์ด๋ ‡๊ฒŒ ORDER๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด menusObservable์— ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋™์ž‘์„, ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•˜๋ฉด

์‹ค์ œ ์›ํ•˜๋Š”๋Œ€๋กœ ์ž˜ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

 

๊ทธ๋Ÿผ ์ด์ œ clear๋ฅผ ๋ˆ„๋ฅด๋ฉด, ์ฃผ๋ฌธ ๊ธˆ์•ก๊ณผ ์ฃผ๋ฌธ ๊ฐฏ์ˆ˜๋ฅผ ์ดˆ๊ธฐํ™” ํ•˜๋Š” ์ฝ”๋“œ ์ž‘์„ฑ์„ ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

@IBAction func onClear() {
        viewModel.clearAllItemSelections()
    }

์šฐ์„  ์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ, viewModel์„ ํ†ตํ•ด clearAllItemSelections()๋ฅผ ํ˜ธ์ถœํ•ฉ์‹œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ viewModelํŒŒ์ผ์— ๊ฐ€์„œ ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ๋ด…์‹œ๋‹ค.

func clearAllItemSelections(){
        menusObservable
            .map {
                $0.map{ m in
                    Menu(name: m.name, price: m.price, count: 0)
                }
            }
            .subscribe {
                self.menusObservable.onNext($0)
            }
    }

์œ„์™€๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด, ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ ๋  ๋•Œ ๋งˆ๋‹ค menusObservable์˜ ๋ฐ์ดํ„ฐ๋ฅผ count๊ฐ€ 0์ธ ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ 

๋‹ค์‹œ .subscribeํ•˜์—ฌ ์ƒˆ๋กœ์šด stream์„ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฐ๋ฐ, ์šฐ๋ฆฌ๊ฐ€ viewDidLoad์— .subscribeํ•˜์—ฌ ๋งŒ๋“  stream์€ App LifeCycle์— ์˜ํ•ด ํ•ด๋‹น View์—์„œ ๋”ฑ 1๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜๊ณ , View๊ฐ€ ์‚ฌ๋ผ์งˆ ๋•Œ ์ž๋™์œผ๋กœ dispose๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ ‡์ง€๋งŒ ์šฐ๋ฆฌ์˜ ์ฝ”๋“œ๋Š” clear๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ ๋งˆ๋‹ค clearAllItemSelections()๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์—,

๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ ๋งˆ๋‹ค .subscribe()๋ฅผ ํ†ตํ•ด ๊ณ„์† ์ƒˆ๋กœ์šด stream์„ ๋งŒ๋“ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

func clearAllItemSelections(){
        menusObservable
            .map {
                $0.map{ m in
                    Menu(name: m.name, price: m.price, count: 0)
                }
            }
            .take(1)
            .subscribe {
                self.menusObservable.onNext($0)
            }
    }

๋”ฐ๋ผ์„œ, ์œ„์˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด  .take()์ด๋ผ๋Š”operator๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ 1๋ฒˆ ์‹คํ–‰ํ•˜๋ฉด์ž๋™์œผ๋กœ ํ•ด๋‹น stream์ด dispose๋˜๊ฒŒ ๋งŒ๋“ค์–ด์„œ

๋ฌด์˜๋ฏธํ•œ stream์ด ๊ณ„์† ์‚ด์•„์žˆ๋Š” ๊ฒƒ์„ ๋ง‰์•„์ค๋‹ˆ๋‹ค.

 

 

 

 

 

 


 

 

 

+

์‚ฌ์‹ค, ํ•ด๋‹น View์—์„œ์˜ ๋งˆ์ง€๋ง‰ ๊ธฐ๋Šฅ์ธ ์ฃผ๋ฌธ ๊ฐœ์ˆ˜ ์ถ”๊ฐ€/๊ฐ์†Œ ๊ธฐ๋Šฅ์ด ๋‚จ์•˜์Šต๋‹ˆ๋‹ค.

์™ผ์ชฝ์˜ + - ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด, ํ•ด๋‹น ์ƒํ’ˆ์˜ ๊ฐฏ์ˆ˜๋ฅผ ์„ค์ • ๊ฐ€๋Šฅํ•˜๋‹ค.

ํ•˜์ง€๋งŒ ์ง€๊ธˆ๊นŒ์ง€ ๊ณต๋ถ€ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์ž˜ ์‚ฌ์šฉํ•˜๋ฉด, ์ด ์ฃผ๋ฌธ ๊ฐœ์ˆ˜๋ฅผ ์กฐ์ ˆํ•˜๋Š” ๊ธฐ๋Šฅ๋„ ์ถฉ๋ถ„ํžˆ ๋งŒ๋“ค์–ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, ์ด ๋ถ€๋ถ„์€ ์ž๋ฃŒ๋ฅผ ์•ˆ ๋ณด๊ณ  ์ง์ ‘ ๋งŒ๋“ค์–ด ๋ณด์‹œ๋Š” ๊ฒƒ์„ ์ถ”์ฒœ ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

 

728x90
๋ฐ˜์‘ํ˜•
๋Œ“๊ธ€
๋ฐ˜์‘ํ˜•
๋งํฌ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
Total
Today
Yesterday