UIPickerView 써보기

1 답변 글타래를 보이고 있습니다
  • 글쓴이
    • 쥬트
      참가자
      • 글작성 : 9
      • 답글작성 : 8

      앱에서 사용자의 출생연도를 입력 받아야 할 때가 있었다. Date Picker로 좀 더 자세한 생년월일을 받을 수도 있었지만 자세하게 받을 필요가 없었기 때문에 출생연도만 받는 걸로 합의를 봤었다.
      그래서 Date Picker의 부모 클래스? 라고도 할 수 있는 Picker View를 살짝 커스텀 해서 사용해 보았다.

      먼저 Picker View를 하나 생성하여 Text Field의 input view 로 설정한다. 또한 커스텀을 위해서 Picker View의 delegate 와 dataSource 도 지정해주어야 한다.

      func createYearPicker(){
              let yearPicker = UIPickerView()
              yearPicker.delegate = self
              yearPicker.dataSource = self
              userAgeTxtField.inputView = yearPicker
      }
      

      또 편한 입력을 위해 ToolBar도 설정해 주었다.

      func createToolBar(){
              let toolBar = UIToolbar()
              toolBar.sizeToFit()
              let doneBtn = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(SurveyInfoVC.dismissKeyboard))
              let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
              toolBar.setItems([flexibleSpace,doneBtn], animated: false)
              userAgeTxtField.inputAccessoryView = toolBar
          }
      

      done 버튼을 추가하여 액션을 지정해 주고, 오른쪽 끝에 있는게 좀 더 편의성이 있지 않을까 해서 flexibleSpace를 생성해서 toolBar의 아이템으로 설정하였다.
      이렇게 지정한 뒤에 Delegate와 DataSource에 Picker View 안에 제공할 선택지와 선택했을 때 이벤트를 지정해주면 끝이다.
      DataSource 프로토콜을 먼저 살펴보면

          // returns the number of 'columns' to display.
          @available(iOS 2.0, *)
          func numberOfComponents(in pickerView: UIPickerView) -> Int
          // returns the # of rows in each component..
          @available(iOS 2.0, *)
          func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
      

      열의 개수, 즉 선택할 속성을 정할 수 있고 각 속성의 행의 개수도 지정할 수 있다.
      따라서 출생연도만을 받기 때문에 컴포넌트의 갯수는 1이고 출생 연도 선택지로 미리 만들어 놓은 배열의 count를 리턴하도록 하였다.

      extension SurveyInfoVC: UIPickerViewDataSource{
          func numberOfComponents(in pickerView: UIPickerView) -> Int {
              return 1
          }
          func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
              return bornInYearList.count
          }
      }
      

      다음은 Delegate 프로토콜이다.

          // returns width of column and height of row for each component.
          @available(iOS 2.0, *)
          optional func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat
          @available(iOS 2.0, *)
          optional func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat
          // these methods return either a plain NSString, a NSAttributedString, or a view (e.g UILabel) to display the row for the component.
          // for the view versions, we cache any hidden and thus unused views and pass them back for reuse.
          // If you return back a different object, the old one will be released. the view will be centered in the row rect
          @available(iOS 2.0, *)
          optional func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
          @available(iOS 6.0, *)
          optional func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? // attributed title is favored if both methods are implemented
          @available(iOS 2.0, *)
          optional func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView
          @available(iOS 2.0, *)
          optional func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
      

      다양한 메소드들 이있는데 대략적으로 소개하자면 각 컴포넌트의 너비를 지정하거나, 행 별로 높이를 지정할 수 있고, 각 행의 들어갈 title 또는 AttributedTitle을 넣을 수 있고, 이미지뷰나 커스텀한 UIView를 넣을 수도 있다고 한다 ..!
      마지막으로 선택했을 때의 이벤트를 지정할 수도 있다.
      내가 필요한 건 간단한 커스텀이였기 때문에 몇가지만 사용하였다.

      extension SurveyInfoVC: UIPickerViewDelegate{
          func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
              return "\(bornInYearList[row])"
          }
          func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
              selectedYear = "\(bornInYearList[row])"
              …
          }
      }
      

      먼저 각 행에 들어갈 Title을 설정하였는데 이 전에 설정한 배열로 지정해 주었고, 선택 값을 다른 변수에 저장해 주는 이벤트도 지정해 주었다.

    • 야곰
      키 마스터
      • 글작성 : 37
      • 답글작성 : 579

      좋은 글 고맙습니다!
      titleForRow메서드의 반환값을 return "\(row+1970)" 처럼 해주면 어떨까요?
      보여줄 생년월일을 배열로 미리 만들어 놓은 이유가 따로 있나요? 🙂

1 답변 글타래를 보이고 있습니다
  • 답변은 로그인 후 가능합니다.

logo landscape small

사업자번호 : 743-81-02195
통신판매업 신고번호 : 제 2022-충북청주-1278 호
고객센터 : 카카오톡채널 @yagom