0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

🩰yawacom - 🐥画面を作っていく

Posted at

2021/02/26現在編集中

ログイン画面の作成

1つ前の記事でユーザ登録画面を作った要領でログイン画面も作っていきます.
下記のような流れになるように作っていきます.
今回はおおまかに3つ
💡テキストボックスとボタンで構成されるログイン画面を作る
💡ログイン画面から新規登録画面に遷移するボタンがある
💡ログインしたらやわらかさを記入する画面に遷移する
これらの動きを持つ画面を作ります!

💡テキストボックスとボタンで構成されるログイン画面を作る

まずはユーザ名・パスワードを打つためのテキストボックス2つとログインボタンを作ります.一つ前の記事の要領でとりあえずviewDidLoadにぶちこんでます🙇🏻‍♂️
またtextFieldShouldReturnを使用して,テキストボックスに文字を入力して改行を押したらキーボードが隠れるようにします.これをしないとユーザー名などを打ち込んでもキーボードがしまえずログインボタンが押せないハメになります.

LoginViewController.swift
    override func viewDidLoad() {
        super.viewDidLoad()
        print("ログインビューコントローラー")
        
        self.viewModel = LoginViewModel()
        
        self.view.backgroundColor = .white
        self.userName.backgroundColor = UIColor(named: "textbox")
        self.password.backgroundColor = UIColor(named: "textbox")
        self.loginButton.backgroundColor = .systemGray
        self.loginButton.tintColor = .white
        self.loginButton.layer.cornerRadius = 10
        
        // textFiel の情報を受け取るための delegate を設定するとtextFieldShouldReturnとかが呼ばれる
        self.userName.delegate = self
        self.password.delegate = self
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            // キーボードを閉じる
            textField.resignFirstResponder()
            return true
    }

するとこんな感じの画面が作れます.

💡ログイン画面から新規登録画面に遷移する

ログインボタンの下にある『新規登録する』(registraionButton)を押すと新規登録画面に遷移するようにします.
流れとしては

  1. LoginViewController で registraionButton の input(onTapRegistraionButton) を作ってTap判定する
  2. LoginViewModel で input の registraionButton を showRegistraionView にいれる
  3. LoginViewModel の output に showRegistraionView をいれる
  4. LoginViewController の output.showRegistraionView で遷移先のVCをstartする
    のようになります.

1. LoginViewController で registraionButton の input(onTapRegistraionButton) を作ってTap判定する

とりあえずLoginViewModelのファイルだけ生成します.ファイルの新規作成をして中身は下記のように用意しておきます.

LoginViewModel.swift
import Foundation
import RxSwift
import RxCocoa

class LoginViewModel: ViewModelType {
    private let bag = DisposeBag()

    func transform(input: Input) -> Output {
    }

    struct Input {
        let onTapRegistraionButton: Signal<Void>    // onTapRegistraionButtonをTapしたかをいれる
    }

    struct Output {
        let showRegistraionView: Driver<Void>    // 新規登録画面に遷移するかどうかをいれる
    }
}

次にLoginViewControllerでLoginViewModelを宣言し,viewDidLoadでLoginViewModelのtransform関数を呼ぶようにします.

LoginViewController.swift
    private var viewModel: LoginViewModel!

    override func viewDidLoad() {
        super.viewDidLoad()

        ...

        let input = createInput()
        let output = viewModel.transform(input: input)
        setupOutput(output)
    }

さて中身を書いていきます❣️

LoginViewControllerで『registraionButtonを押した!』という判定をします.ここではRxSwiftのrx.tap.asSignal()を使用します.

LoginViewController.swift
private func createInput() -> LoginViewModel.Input {
        return LoginViewModel.Input(
            onTapRegistraionButton: self.registraionButton.rx.tap.asSignal()
        )
    }

2. LoginViewModel で input の registraionButton を showRegistraionView にいれる

1のLoginViewControllerでTapしたかどうかを.emitで監視します👀
『押された!』ってなったらshowRegistraionViewをacceptします.

LoginViewModel.swift
    func transform(input: Input) -> Output {
        let showRegistraionView = PublishRelay<Void>()
        
        input.onTapRegistraionButton
            .emit(onNext: {
                showRegistraionView.accept(())
            })
            .disposed(by: self.bag)
        
        return LoginViewModel.Output(
            showRegistraionView: showRegistraionView.asDriverOnErrorJustComplete()
        )
    }

3. LoginViewModel の output に showRegistraionView をいれる

2でacceptされたらOutputにいれることで『新規登録画面に遷移していいよ!』ってことを知らせます.
2のコードの

LoginViewModel.swift
        return LoginViewModel.Output(
            showRegistraionView: showRegistraionView.asDriverOnErrorJustComplete()
        )

ここの部分です.

4. LoginViewController の output.showRegistraionView で遷移先のVCをstartする

3のOutputでLoginViewModelから『新規登録画面に遷移していいよ!』と送られてきたかどうかを.drive(onNext:で監視します👀
送られてきたら前の記事の要領でRegistrationViewController.start(self)で画面遷移します!

LoginViewController.swift
    private func setupOutput(_ output: LoginViewModel.Output) {
        output.showRegistraionView
            .drive(onNext: { [unowned self] in
                RegistrationViewController.start(self)
            }).disposed(by: bag)
    }

以上で新規登録画面に遷移ができます!
前の記事から新規登録画面の見た目をすこし変えてしまいましたが,動きはこんな感じになります.

💡ログインしたらやわらかさを記入する画面に遷移する

途中です🙇🏻‍♂️

詰まったところ

LoginViewController.swift
    private let viewModel: LoginViewModel

    init(viewModel: LoginViewModel) {
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
    }

    @available(*, unavailable)
    required init?(coder _: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

このように書くとstartのところの

LoginViewController.swift
let nextVC = LoginViewController(nibName: "LoginView", bundle: nil)

Type of expression is ambiguous without more contextというエラーになってしまう.
なので今回はinitを省略しvarなどの宣言には!をつけています.(!がないと'LoginViewController' has no initializersになる)

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?