[RxCocoa] Alert Controller

RudinP·3일 전
0

Study

목록 보기
375/375
  • alertController을 Observable로 래핑한 다음, action에서 이벤트를 방출하는 패턴으로 구현
  • 경고창을 표시하는 것은 CocoaTouch와 동일

1. 1개의 액션

enum ActionType {
    case ok
    case cancel
}

extension UIViewController {
    func info(title: String, message: String? = nil) -> Observable<ActionType> {
        //추가적인 작업을 위해 ActionType 사용. 아니라면 Void나 Completable 도 ok
        return Observable.create { [weak self] observer in
            let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
            
            let okAction = UIAlertAction(title: "Ok", style: .default) { _ in
                //#2 차이: 이벤트를 전달하도록 구현(액션 구현 X)
                observer.onNext(.ok)
                observer.onCompleted()
            }
            
            alert.addAction(okAction)
            self?.present(alert, animated: true, completion: nil)
            
            //#1 차이: 생성 시점에 클로저 전달, alertController을 dismiss
            return Disposables.create {
                alert.dismiss(animated: true, completion: nil)
            }
        }
    }
}
class RxCocoaAlertViewController: UIViewController {
    
    let bag = DisposeBag()
    
    @IBOutlet weak var colorView: UIView!
    
    @IBOutlet weak var oneActionAlertButton: UIButton!
    
    @IBOutlet weak var twoActionsAlertButton: UIButton!
    
    @IBOutlet weak var actionSheetButton: UIButton!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        oneActionAlertButton.rx.tap
            .flatMap { [unowned self] in
                self.info(title: "Current Color", message: self.colorView.backgroundColor?.rgbHexString)}
            .subscribe(onNext: { [unowned self] actionType in
                //#3 여기로 클로저에서 방출된 액션타입이 전달됨
                switch actionType {
                case .ok:
                    print(self.colorView.backgroundColor?.rgbHexString ?? "")
                default:
                    break
                }
            })
            .disposed(by: bag)
        
    }
}

2. 2개의 액션

~extension
    func alert(title: String, message: String? = nil) -> Observable<ActionType> {
        return Observable.create { [weak self] observer in
            let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
            
            let okAction = UIAlertAction(title: "Ok", style: .default) { _ in
                //#2 차이: 이벤트를 전달하도록 구현(액션 구현 X)
                observer.onNext(.ok)
                observer.onCompleted()
            }
            alert.addAction(okAction)
            
            let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { _ in
                observer.onNext(.cancel)
                observer.onCompleted()
            }
            alert.addAction(cancelAction)
            
            self?.present(alert, animated: true, completion: nil)
            
            //#1 차이: 생성 시점에 클로저 전달, alertController을 dismiss
            return Disposables.create {
                alert.dismiss(animated: true, completion: nil)
            }
        }
~ viewDidLoad
        twoActionsAlertButton.rx.tap
            .flatMap { [unowned self] in
                self.alert(title: "Reset Color", message: "Reset to black color?") }
            .subscribe(onNext: { [unowned self] actionType in
                switch actionType {
                case .ok:
                    self.colorView.backgroundColor = UIColor.black
                default:
                    break
                }
            })
            .disposed(by: bag)

3. 액션시트

~extension
    func colorActionSheet(colors: [UIColor], title: String, message: String? = nil) -> Observable<UIColor> {
        return Observable.create { [weak self] observer in
            let actionSheet = UIAlertController(title: title, message: message, preferredStyle: .actionSheet)
            
            for color in colors {
                let colorAction = UIAlertAction(title: color.rgbHexString, style: .default) { _ in
                    observer.onNext(color)
                    observer.onCompleted()
                }
                actionSheet.addAction(colorAction)
            }
            
            let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { _ in
                observer.onCompleted()
            }
            actionSheet.addAction(cancelAction)
            
            self?.present(actionSheet, animated: true, completion: nil)
            
            return Disposables.create {
                actionSheet.dismiss(animated: true, completion: nil)
            }
        }
    }
~viewDidLoad
        actionSheetButton.rx.tap
            .flatMap { [unowned self] in
                self.colorActionSheet(colors: MaterialBlue.allColors, title: "Change Color", message: "Choose one")
            }
            .subscribe(onNext: { [unowned self] color in
                self.colorView.backgroundColor = color
            })
            .disposed(by: bag)
profile
iOS 개발자가 되기 위한 스터디룸/스터디의 레퍼런스는 모두 kxcoding

0개의 댓글