Iganinのブログ

日頃の開発で学んだ知見を中心に記事を書いています。

【iOS】単位付きのUITextFieldを作る方法とカスタムクラス

はじめに

ユーザーからの情報の入力の際にTextViewと並んでUITextFieldはよく使われます。 単位付きの入力にしたい場合は、UITextFieldの範囲外にUILabelを設置する、 入力値に単位をつけ、それを特別扱いするようDelegateメソッド内で 対応するといった方法がありますが、今ひとつ実装が面倒なのが正直なところです。

本記事では単位付きのUITextFieldを簡単に作成する方法とカスタムクラスのご紹介をします。

環境設定

以下の環境を使用しています。

  • Xcode10.2.1
  • Swift 5.0.1

方法

UITextFieldには、leftView, leftViewMode, rightView, rightViewModeというプロパティがあります。 それぞれUITextFieldの左側のView, 右側に設置するViewおよびそれらをどのように表示するかを指定できます。

なお、ViewModeには以下の設定値があります。

    public enum ViewMode : Int {
        case never // 出さない
        case whileEditing // 編集中のみ出す
        case unlessEditing // 編集中意外に出す
        case always // 常時出す
    }

したがって、leftView, rightViewにUILabelを設定し、適切なViewModeを設定することでUITextFieldに簡単に単位をつけることができます。 なお、leftView, rightViewはUIViewなので、それを継承したUIImageViewなども入れられるはずです。(試してはいません)

カスタムしたUITextField

アプリ作成時に簡単に使用できるように、単位を簡単につけられるUITextFieldを作成しました。

import Foundation
import UIKit

@IBDesignable
public final class WithUnitTextField: UITextField {
    
    @IBInspectable
    public var prefix: String?
    
    @IBInspectable
    public var suffix: String?
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    
    public override func awakeFromNib() {
        super.awakeFromNib()
        commonInit()
    }

    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
      
    public override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        commonInit()
    }
}

private extension WithUnitTextField {

    func commonInit() {
        // ViewMode常時出す設定にしているが必要に応じて変更すること
        // IBInspectableで設定できるようにしてもいいかもしれない
        
        let leftLabel = UILabel(frame: .zero)
        leftLabel.font = font
        leftLabel.text = prefix
        leftLabel.sizeToFit()
        leftView = leftLabel
        leftViewMode = .always
        
        // FontはUITextFieldのFontと同様にしているが、
        // こちらもIBInspectableで設定できるようにしてもいいかもしれない
        
        let rightLabel = UILabel(frame: .zero)
        rightLabel.font = font
        rightLabel.text = suffix
        rightLabel.sizeToFit()
        rightView = rightLabel
        rightViewMode = .always
    }
    
}

例えばですが、下記画像のようなTextFieldがInterface Builder上のみで簡単に作成できます。

f:id:Iganin:20190620003258p:plain

まとめ

単位付きのUITextFieldを作成する方法と、それを活かしたカスタムクラスのコードをご紹介しました。 要件として求められた際にはぜひ選択肢の一つとしてご検討ください。

参考