LoginSignup
1
0

More than 1 year has passed since last update.

MVVMSample

Last updated at Posted at 2022-07-18

はじめに

RxSwift勉強中です。
今回は

を参考に、MVVMについて勉強したので、アウトプットしていきたいと思います。
とても解りやすくまとめられていて、すごく勉強になりました😁
ありがとうございました!!
今回は、よくあるログイン画面を作成しました。

コード全文

ViewController
import UIKit
import RxCocoa
import RxSwift

class ViewController: UIViewController {
    
    @IBOutlet private weak var nameTextField: UITextField!
    @IBOutlet private weak var passwordTextField: UITextField!
    @IBOutlet private weak var passwordConfirmTextField: UITextField!
    @IBOutlet private weak var validationLabel: UILabel!
    @IBOutlet private weak var loginButton: UIButton!
    
    private let disposeBag = DisposeBag()
    private var viewModel: ViewModel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupViewModel()
    }
    private func setupViewModel(){
        // ユーザーからの情報をViewModelへ送る
        viewModel = ViewModel(
            nameText: nameTextField.rx.text.orEmpty
                .asDriver(),
            passwordText: passwordTextField.rx.text.orEmpty
                .asDriver(),
            passwordConfirmText: passwordConfirmTextField.rx.text.orEmpty.asDriver()
        )
        // validationResultの処理をViewControllerにバインディング(drive)している
        viewModel.validationResult.drive(onNext: { result in
            self.loginButton.isEnabled = result.isValidated
            self.loginButton.alpha = result.buttonAlpha
            self.validationLabel.text = result.text
            self.validationLabel.textColor = result.textColor
        }).disposed(by: disposeBag)
    }
        //アラート処理
    @IBAction func loginButtonTapped(_ sender: Any) {
        let alert = UIAlertController(title: "登録しました", message: "\(nameTextField.text!)", preferredStyle: .alert)
        let ok = UIAlertAction(title: "OK", style: .cancel)
        alert.addAction(ok)
        self.present(alert, animated: true, completion: nil)
    }
}
ViewModel
import RxSwift
import RxCocoa

class ViewModel {
// Validationの結果をenumで表現している
    let validationResult: Driver<ValidationResult>
// 3つのTextFieldが空欄かどうかをBool値で表現している
    let blankValidation: Driver<Bool>
// パスワードと確認用パスワードが一致しているかをBool値で表現している
    let passwordConfirmValidation: Driver<Bool>
    
    init(nameText: Driver<String>, passwordText: Driver<String>, passwordConfirmText: Driver<String>) {
        
        let validationModel = ValidationModel()
        
        blankValidation = Driver.combineLatest(nameText, passwordText, passwordConfirmText) {
            name, password, passwordConfirm in
            return validationModel.blankValidation(text: [name, password, passwordConfirm])
        }
        passwordConfirmValidation = Driver.combineLatest(passwordText, passwordConfirmText) {
            password, passwordConfirm in
            return validationModel.passwordConfirmValidation(password: password, passwordConfirm: passwordConfirm)
        }
        
        validationResult = Driver.combineLatest(blankValidation, passwordConfirmValidation) {
            blankValidation, passwordConfirmValidation in
            if !blankValidation {
                return .blankError
            } else if !passwordConfirmValidation {
                return .passwordConfirmError
            }else {
                return .ok
            }
        }
    }
}
ValidationModel
import UIKit

enum ValidationResult {
    
    case ok
    case blankError
    case passwordConfirmError
    
    var isValidated: Bool {
        switch self {
        case .ok: return true
        case .blankError, .passwordConfirmError: return false
        }
    }
    var text: String {
        switch self {
        case .ok: return "登録可能です"
        case .blankError: return "空欄があります"
        case .passwordConfirmError: return "パスワードが確認用と一致していません"
        }
        
    }
    var textColor: UIColor {
        switch self {
        case .ok: return .green
        case .blankError, .passwordConfirmError: return .red
        }
    }
    var buttonAlpha: CGFloat {
        switch self {
        case .ok: return 1.0
        case .blankError, .passwordConfirmError: return 0.4
        }
    }
}

class ValidationModel {
    
    func blankValidation(text: [String]) -> Bool {
        for text in text {
            if text.isEmpty {
                return false
            }
        }
        return true
    }
    func passwordConfirmValidation(password: String, passwordConfirm: String) -> Bool {
        return password == passwordConfirm
    }
}

今回はDriverを使って表現していましたが、まだまだ自分にはDriverやRelay等、理解しきれていない部分が多々あるので、今回のアプリのObservarやRelayを使って同じ挙動を作り、より深く理解していきたいと思います。

以上です!!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0