Skip to content

Commit

Permalink
[Feat] RxSwift로 구현된 부분 Combine으로 변경
Browse files Browse the repository at this point in the history
  • Loading branch information
yangsubinn committed Sep 26, 2022
1 parent c74781f commit 783fd5f
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 54 deletions.
98 changes: 74 additions & 24 deletions MVVM-RxSwift/MVVM-RxSwift/TestViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,103 @@
// Created by 양수빈 on 2022/09/24.
//

import RxSwift
import RxRelay
//import RxSwift
//import RxRelay
import Combine

class TestViewModel: ViewModelType {

private let disposeBag = DisposeBag()
// Rx
// private let disposeBag = DisposeBag()

// Combine
private var cancelBag = Set<AnyCancellable>()

struct Input {
let email: Observable<String?>
let password: Observable<String?>
let tapLogIn: Observable<UserData>
// Rx
// let email: Observable<String?>
// let password: Observable<String?>
// let tapLogIn: Observable<UserData>

// Combine
let email: AnyPublisher<String?, Error>
let password: AnyPublisher<String?, Error>
let tapLogin: AnyPublisher<UserData, Error>
}

struct Output {
let enableLogInButton = BehaviorRelay<Bool>(value: false)
let errorMessage = PublishRelay<String>()
let logInSuccess = PublishRelay<Void>()
// Rx
// let enableLogInButton = BehaviorRelay<Bool>(value: false)
// let errorMessage = PublishRelay<String>()
// let logInSuccess = PublishRelay<Void>()

// Combine
let enableLogInButton = CurrentValueSubject<Bool, Error>.init(false)
let errorMessage = PassthroughSubject<String, Error>()
let logInSuccess = PassthroughSubject<Void, Error>()
}

init() { }
}

extension TestViewModel {
/// CleanArchitecture: - input에 따라 useCase로 연결
func transform(from input: Input, disposeBag: DisposeBag) -> Output {
// Rx
// func transform(from input: Input, disposeBag: DisposeBag) -> Output {
// let output = Output()
//// self.bindOutput(output: output, disposeBag: disposeBag)
//
// Observable.combineLatest(input.email, input.password)
// .filter { $0.0 != nil && $0.1 != nil }
// .subscribe(onNext: { str in
// if str.0!.count > 0 && str.1!.count > 0 {
// output.enableLogInButton.accept(true)
// } else {
// output.enableLogInButton.accept(false)
// }
// })
// .disposed(by: disposeBag)
//
// input.tapLogIn.subscribe(onNext: { data in
// if data.email == "subin" && data.password == "0000" {
// print("로그인 경축")
// } else {
// print("로그인 실패")
// }
// })
// .disposed(by: disposeBag)
//
// return output
// }

// Combine
func transform(from input: Input) -> Output {
let output = Output()
// self.bindOutput(output: output, disposeBag: disposeBag)

Observable.combineLatest(input.email, input.password)
input.email.combineLatest(input.password)
.filter { $0.0 != nil && $0.1 != nil }
.subscribe(onNext: { str in
.sink(receiveCompletion: { event in
print("completion \(event)")
}, receiveValue: { str in
if str.0!.count > 0 && str.1!.count > 0 {
output.enableLogInButton.accept(true)
output.enableLogInButton.send(true)
} else {
output.enableLogInButton.accept(false)
output.enableLogInButton.send(false)
}
})
.disposed(by: disposeBag)
.store(in: &cancelBag)

input.tapLogIn.subscribe(onNext: { data in
if data.email == "subin" && data.password == "0000" {
print("로그인 경축")
} else {
print("로그인 실패")
}
})
.disposed(by: disposeBag)
input.tapLogin
.sink(receiveCompletion: { event in
print("completion \(event)")
}, receiveValue: { value in
if value.email == "subin" && value.password == "0000" {
print("로그인 경축")
} else {
print("로그인 실패")
}
})
.store(in: &cancelBag)

return output
}
Expand Down
91 changes: 65 additions & 26 deletions MVVM-RxSwift/MVVM-RxSwift/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
//

import UIKit
import RxSwift
import RxCocoa
//import RxSwift
//import RxCocoa
import Combine

class ViewController: UIViewController {

Expand All @@ -19,11 +20,17 @@ class ViewController: UIViewController {

// MARK: - Properties

private var loginButtonClicked = PublishSubject<UserData>()
private var emailEditEventFinished = PublishSubject<String?>()
private var pwEditEvendFinished = PublishSubject<String?>()
private var disposeBag = DisposeBag()
var viewModel = TestViewModel()
// Rx
// private var loginButtonClicked = PublishSubject<UserData>()
// private var emailEditEventFinished = PublishSubject<String?>()
// private var pwEditEvendFinished = PublishSubject<String?>()
// private var disposeBag = DisposeBag()
// Combine
private var loginButtonClicked = PassthroughSubject<UserData, Error>()
private var emailEditEventFinished = PassthroughSubject<String?, Error>()
private var pwEditEvendFinished = PassthroughSubject<String?, Error>()
private var cancelBag = Set<AnyCancellable>()

// MARK: - Life Cycles

Expand All @@ -36,7 +43,7 @@ class ViewController: UIViewController {
setDelegate()
setButtonState(false)
bindViewModels()
setButtonAction()
// setButtonAction()
}

override func viewDidDisappear(_ animated: Bool) {
Expand Down Expand Up @@ -65,6 +72,9 @@ class ViewController: UIViewController {
private func addTargets() {
self.emailTextField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged)
self.pwTextField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged)

// combine
self.loginButton.addTarget(self, action: #selector(setButtonAction), for: .touchUpInside)
}

private func setButtonState(_ enable: Bool) {
Expand All @@ -87,19 +97,27 @@ class ViewController: UIViewController {
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}

private func setButtonAction() {
self.loginButton.rx.tap
.bind {
let userData = UserData(
email: self.emailTextField.text ?? "-",
password: self.pwTextField.text ?? "--")
self.loginButtonClicked.onNext(userData)
}
.disposed(by: disposeBag)
}
// RxCocoa
// private func setButtonAction() {
// self.loginButton.rx.tap
// .bind {
// let userData = UserData(
// email: self.emailTextField.text ?? "-",
// password: self.pwTextField.text ?? "--")
// self.loginButtonClicked.onNext(userData)
// }
// .disposed(by: disposeBag)
// }

// MARK: - @objc

@objc func setButtonAction() {
let userData = UserData(
email: self.emailTextField.text ?? "-",
password: self.pwTextField.text ?? "--")
self.loginButtonClicked.send(userData)
}

@objc func keyboardMoveUp(_ notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
UIView.animate(withDuration: 0.3, animations: {
Expand All @@ -114,25 +132,46 @@ class ViewController: UIViewController {
}

@objc func textFieldDidChange(_ sender: Any?) {
self.emailEditEventFinished.onNext(self.emailTextField.text)
self.pwEditEvendFinished.onNext(self.pwTextField.text)
// Rx
// self.emailEditEventFinished.onNext(self.emailTextField.text)
// self.pwEditEvendFinished.onNext(self.pwTextField.text)

// Combine
self.emailEditEventFinished.send(self.emailTextField.text)
self.pwEditEvendFinished.send(self.pwTextField.text)
}
}

extension ViewController {
private func bindViewModels() {
// Rx
// let input = TestViewModel.Input(
// email: emailEditEventFinished.asObservable(),
// password: pwEditEvendFinished.asObservable(),
// tapLogIn: loginButtonClicked)
// let output = self.viewModel.transform(from: input, disposeBag: disposeBag)
//
// output.enableLogInButton
// .subscribe(onNext: { [weak self] state in
// guard let self = self else { return }
// self.setButtonState(state)
// })
// .disposed(by: disposeBag)

// Combine
let input = TestViewModel.Input(
email: emailEditEventFinished.asObservable(),
password: pwEditEvendFinished.asObservable(),
tapLogIn: loginButtonClicked)
let output = self.viewModel.transform(from: input, disposeBag: disposeBag)
email: emailEditEventFinished.eraseToAnyPublisher(),
password: pwEditEvendFinished.eraseToAnyPublisher(),
tapLogin: loginButtonClicked.eraseToAnyPublisher())
let output = self.viewModel.transform(from: input)

output.enableLogInButton
.subscribe(onNext: { [weak self] state in
guard let self = self else { return }
.sink(receiveCompletion: { completion in
print("completed")
}, receiveValue: { state in
self.setButtonState(state)
})
.disposed(by: disposeBag)
.store(in: &cancelBag)
}
}

Expand Down
12 changes: 8 additions & 4 deletions MVVM-RxSwift/MVVM-RxSwift/ViewModelType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
//

import Foundation
import RxSwift
//import RxSwift

protocol ViewModelType{
associatedtype Input
associatedtype Output
associatedtype Input
associatedtype Output

func transform(from input: Input, disposeBag: DisposeBag) -> Output
// Rx
// func transform(from input: Input, disposeBag: DisposeBag) -> Output

// Combine
func transform(from input: Input) -> Output
}

0 comments on commit 783fd5f

Please sign in to comment.