Help us understand the problem. What is going on with this article?

年と月だけのDatePickerを作る

More than 3 years have passed since last update.

DatePickerを作るには通常UIDatePickerを利用するが、UIDatePickerModeに年と月だけのピッカーはない。UIPickerViewを利用して実装する。実行環境はXcode7.1.1。

StoryBoardで指定したViewControllerに、UIPickerViewDelegateUIPickerViewDataSourceを継承する。UITableViewと実装の方法は似ている。

  • viewDidLoad()において、UITextFieldinputViewUIPickerViewをセット、delegateで処理を委譲
  • numberOfComponentsInPickerView(_:)UIPickerViewの要素数 (Component) を設定
    • 今回のケースでは「年」と「月」の2つ
  • pickerView(_:numberOfRowsInComponent:)UIPickerViewのComponentごとのrowの数を設定
    • 「年」は1965 ~ 2015、「月」は1 ~ 12
  • pickerView(_:titleForRow:forComponent:)で各Componentの各rowのタイトル名を設定

これで年と月のDatePickerの見た目ができる。
さらに、DatePickerのピッカーを選択した時にUITextFieldtextに値が自動で入るよう、pickerView(_:didSelectRow:inComponent:)に処理を追加。selectedRowInComponentで指定したインデックスのComponentで選択した値を取得できるので、それを挿入。

これまでの内容をコードにすると、以下のようになる。

ViewController.swift
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    var textField = UITextField()

    let years = (1965...2015).map { $0 }
    let months = (1...12).map { $0 }

    override func viewDidLoad() {
        super.viewDidLoad()

        textField = UITextField(frame: CGRectMake(50, 100, view.bounds.size.width - 50 * 2, 36))
        textField.borderStyle = .Line

        let pickerView = UIPickerView()
        pickerView.backgroundColor = UIColor.whiteColor()
        pickerView.delegate = self
        textField.inputView = pickerView        
        view.addSubview(textField)
    }

    // MARK: - UIPickerView data source

    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 2
    }

    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if component == 0 {
            return years.count
        } else if component == 1 {
            return months.count
        } else {
            return 0
        }
    }

    // MARK: - UIPickerView delegate

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if component == 0 {
            return "\(years[row])年"
        } else if component == 1 {
            return "\(months[row])月"
        } else {
            return nil
        }
    }

    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        let year = years[pickerView.selectedRowInComponent(0)]
        let month = months[pickerView.selectedRowInComponent(1)]
        textField.text = "\(year)\(month)月"
    }

}

これだけだと、一度DatePickerを開いたら閉じれなくなってしまうので、キーボードに「完了」ボタンを付けて閉じれるようにする。

UITextFieldinputAccessoryViewに、「完了」ボタンを含むUIViewをセット。

ViewController.swift
func setKeyboardAccessory() {
    let keyboardAccessory = UIView(frame: CGRectMake(0, 0, view.bounds.size.width, 36))
    keyboardAccessory.backgroundColor = UIColor.whiteColor()
    textField.inputAccessoryView = keyboardAccessory

    let topBorder = UIView(frame: CGRectMake(0, 0, keyboardAccessory.bounds.size.width, 0.5))
    topBorder.backgroundColor = UIColor.lightGrayColor()
    keyboardAccessory.addSubview(topBorder)

    let completeButton = UIButton(frame: CGRectMake(keyboardAccessory.bounds.size.width - 48, 0, 48, keyboardAccessory.bounds.size.height - 0.5 * 2))
    completeButton.titleLabel?.font = UIFont.boldSystemFontOfSize(16.0)
    completeButton.setTitle("完了", forState: .Normal)
    completeButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
    completeButton.setTitleColor(UIColor.redColor(), forState: .Highlighted)
    completeButton.addTarget(self, action: "hidePickerView", forControlEvents: .TouchUpInside)
    keyboardAccessory.addSubview(completeButton)

    let bottomBorder = UIView(frame: CGRectMake(0, keyboardAccessory.bounds.size.height - 0.5, keyboardAccessory.bounds.size.width, 0.5))
    bottomBorder.backgroundColor = UIColor.lightGrayColor()
    keyboardAccessory.addSubview(bottomBorder)
}

func hidePickerView() {
    textField.resignFirstResponder()
}

上記のコードをViewController.swiftに追加し、viewDidLoadの中でsetKeyboardAccessory()メソッドを呼び出すようにするとキーボードに「完了」ボタンが付き、DatePickerを閉じることができるようになる。

下のスクショのようなのができる。

Simulator Screen Shot 2015.11.29 21.07.24.png

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away