【Xcode/Swift】数字以外の入力をさせないようにする(UIKit & RxSwift編)

Storyboard

コード

ViewController

import UIKit
import RxSwift
import RxCocoa

final class HomeViewController: UIViewController {

    // MARK: - Properties
    @IBOutlet private weak var textField: UITextField!
    @IBOutlet private weak var nameLabel: UILabel!

    private let viewModel = HomeViewModel()
    private let disposeBag = DisposeBag()

    // MARK: - View Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        bind()
    }

}

// MARK: - Bindings
private extension HomeViewController {
    func bind() {
        textField.rx.text
            .orEmpty
            .bind(to: viewModel.inputs.textFieldInput)
            .disposed(by: disposeBag)

        viewModel.outputs.squareRootOfTwo
            .drive(nameLabel.rx.text)
            .disposed(by: disposeBag)
    }
}

HomeViewModel.swift

import RxSwift
import RxCocoa

protocol HomeViewModelInputs: AnyObject {
    var textFieldInput: PublishRelay<String> { get }
}

protocol HomeViewModelOutputs: AnyObject {
    var squareRootOfTwo: Driver<String> { get }
}

protocol HomeViewModelType: AnyObject {
    var inputs: HomeViewModelInputs { get }
    var outputs: HomeViewModelOutputs { get }
}

class HomeViewModel: HomeViewModelType, HomeViewModelInputs, HomeViewModelOutputs {

    // MARK: - Input Sources
    var textFieldInput = PublishRelay<String>()
    // MARK: - Output Sources
    let squareRootOfTwo: Driver<String>

    // MARK: - Properties
    private let _squareRootOfTwo = BehaviorRelay<String>(value: "")
    private var previousInput = ""
    var inputs: HomeViewModelInputs { return self }
    var outputs: HomeViewModelOutputs { return self }

    private let disposeBag = DisposeBag()

    init() {
        squareRootOfTwo = _squareRootOfTwo.asDriver(onErrorJustReturn: "")

        textFieldInput.asObservable()
            .map { [weak self] newText in
                guard let self = self else { return "" }
                if newText.allSatisfy({ $0.isNumber }) {
                    self.previousInput = newText
                }
                return self.previousInput
            }
            .bind(to: _squareRootOfTwo)
            .disposed(by: disposeBag)
    }

}