iOS
UIPickerView
UIKit
Swift

UIPickerViewのattributedTitleForRowとviewForRowの使い分け

はじめに

UITableViewCellのように「画像とテキスト」を並べたい場合、attributedTitleForRowを使う方法と、viewForRowを使う方法のいずれを採用すべきか。

screenshot.png

結論

横並びの場合、attributedTitleForRowで済ませたほうが実装の簡潔さになります。

これに対して、テキストの上下に画像が配置されるなどレイアウトが複雑になる場合は、viewForRowを使う必要があります。

余談: delegateのメソッドが呼ばれる順番

ところで、UIPickerView delegateのメソッドが呼ばれる順番はどうだったでしょうか。

1. widthForComponent

まず、ローの高さよりも先に幅を指定するメソッドが呼ばれます。

func pickerView(_ pickerView: UIPickerView,
                           widthForComponent component: Int) -> CGFloat

2. rowHeightForComponent

次に、高さです。ここでは、確定したwidthを利用できます。

func pickerView(_ pickerView: UIPickerView,
                           rowHeightForComponent component: Int) -> CGFloat

3. titleForRowなど

実際にローに表示する中身を指定するメソッドが呼ばれます。
3種類ありますが、仮に3つが実装されている場合は、viewForRow > attributedTitleForRow > titleForRow の順番で優先されます。
特にどのメソッドを使うかを指定する必要はありません。コードを書くだけで、優先度の高いメソッドが呼ばれます。

func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView 
func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString?
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?

viewForRowを実装した場合は、attributedTitleForRow以下は無視されます。
attributedTitleForRowとtitleForRowを実装している場合、attributedTitleForRowのreturn がnilのときは、titleForRowが呼ばれます。

関連

UIPickerViewDelegate Reference
実装例 StringPickerPopover.swift