Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIPickerView with attributes string

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? enter image description here

like image 999
MacUserT Avatar asked Dec 05 '25 12:12

MacUserT


1 Answers

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: enter image description here This is the manipulation I would like to do with the text in the picker view.

like image 86
MacUserT Avatar answered Dec 10 '25 08:12

MacUserT



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!