According to Apple's documentation there is a UIPickerView Delegate function called, pickerView(_:attributedTitleForRow:forComponent:). However, I've tried to make it work, but I seem to do something wrong here. I hope someone can help me out.
To make thing easy, I have a simple program that presents the contents of two array in two components of a picker view. The program is simply one view controller and one picker view. The code is presented her:
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
var familyNames = [String]()
var fontName = ""
let firstArray = Array(0...99)
let secondArray = Array(0...99)
let fontCount = 0
@IBOutlet weak var samplePickerView: UIPickerView!
@IBOutlet weak var fontLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
familyNames = UIFont.familyNames.sorted()
let fontNames = UIFont.fontNames(forFamilyName: familyNames[17])
fontName = fontNames.first!
samplePickerView.delegate = self
samplePickerView.dataSource = self
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return firstArray.count
} else {
return secondArray.count
}
}
func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
var rowTitle = ""
let font = UIFont(name: fontName, size: 18.0)
let stringDictionary = [NSAttributedString.Key.font: font]
switch component {
case 0:
rowTitle = String(format: "%03d", firstArray[row])
case 1:
rowTitle = String(format: "%03d", secondArray[row])
default:
break
}
let returnString = NSAttributedString(string: rowTitle, attributes: stringDictionary as [NSAttributedString.Key : Any])
print(returnString)
return returnString
}
}
The picker view should now present the titles in Bradley Hand, so it's easy to spot that is worked.
Unfortunately, the picker view is not presenting the titles in the attributed string. The string returned by the delegate method is an attributed string, so it should work. The pictures shows this is not the case. What am I doing wrong?

After not getting to a solution I requested a DTS at Apple to understand what I was doing wrong. Apparently, I wasn't doing anything wrong, but the method "pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString?" doesn't let you manipulate that much on the attributed string. The answer from Apple was: "UIPickerView’s attributedTitleForRow delegate won’t change the font attribute, but will work for other attributes like font color."
Fortunately, since I wanted to change the font size and font, there is a way to get a different font and font size in the UIPickerView. The solution provided by Apple: "If you want to use all the font attributes available in NSAttributedString, use viewForRow and return a UILabel as an alternative."
The code now looks like this: var familyNames = String var fontName = "" let firstArray = Array(0...99) let secondArray = Array(0...99) let fontCount = 0
@IBOutlet weak var samplePickerView: UIPickerView!
@IBOutlet weak var fontLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
familyNames = UIFont.familyNames.sorted()
let fontNames = UIFont.fontNames(forFamilyName: familyNames[17])
fontName = fontNames.first!
samplePickerView.delegate = self
samplePickerView.dataSource = self
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return firstArray.count
} else {
return secondArray.count
}
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
var rowTitle = ""
let pickerLabel = UILabel()
pickerLabel.textColor = UIColor.blue
switch component {
case 0:
rowTitle = String(format: "%03d", firstArray[row])
case 1:
rowTitle = String(format: "%03d", secondArray[row])
default:
break
}
pickerLabel.text = rowTitle
pickerLabel.font = UIFont(name: fontName, size: 24.0)
pickerLabel.textAlignment = .center
return pickerLabel
}
And the result looks like this:
This is the manipulation I would like to do with the text in the picker view.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With