8

It seems the UIPickerView no longer supports the use of NSAttributedString for picker view items. Can anyone confirm this? I found NS_AVAILABLE_IOS(6_0) in the UIPickerView.h file, but is this the problem? Is there a way around this, or am I out of luck?

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component NS_AVAILABLE_IOS(6_0); // attributed title is favored if both methods are implemented
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;
Rob
  • 1,045
  • 13
  • 28
  • 1
    What happens when you supply an attributed string? How is it not supported? – Wain Sep 22 '13 at 14:57
  • 1
    My apologies I probably should have mentioned this. It runs perfectly fine, but the pickerView does not display it with the specified fonts on iOS 7. It ONLY uses the system default. On iOS 6 this does display in the font it's supposed to. – Rob Sep 22 '13 at 14:59
  • 1
    Did you try returning a label with the attributed text as an alternative approach? – Wain Sep 22 '13 at 15:02
  • 2
    Seems pretty straightforward if it works in iOS6 but not 7. The first thing you should do in this case is build a quick demo app that demonstrates the bug and file a bug report with Apple (bugreporter.apple.com), attaching the demo app. – memmons Sep 22 '13 at 15:03
  • That still works Wain. I don't see how Apple could be unaware of this! – Rob Sep 22 '13 at 15:25
  • I have noticed that fonts have no affect, but NSForegroundColorAttributeName seems to work. – Walter Martin Vargas-Pena Jan 25 '14 at 02:56

3 Answers3

15

The only solution to this problem is apparently to use pickerView:viewForRow:forComponent:reusingView: and return a UILabel with the attributed text, since Apple has apparently disabled using attributed strings otherwise.

Rob
  • 1,045
  • 13
  • 28
  • 1
    The only issue with this approach is that views in picker view don't get the nice zoom effect when selected but strings do. – Indoor Dec 27 '13 at 18:56
  • I agree, and I'm not sure there's actually a way to implement it yourself. It's an unfortunate problem with Apple breaking their own code yet again. – Rob Jan 20 '14 at 01:40
7

Rob is right, bug or not the easiest way to get attributed text in a UIPickerView in iOS 7 is to hack the pickerView: viewForRow: forComponent: reusingView: method. Here's what I did...

-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
    // create attributed string
    NSString *yourString = @"a string";  //can also use array[row] to get string
    NSDictionary *attributeDict = @{NSForegroundColorAttributeName : [UIColor whiteColor]};
    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:yourString attributes:attributeDict];

    // add the string to a label's attributedText property
    UILabel *labelView = [[UILabel alloc] init];
    labelView.attributedText = attributedString;

    // return the label
    return labelView;
}

It looks great on iOS 7, but in iOS 6 the default background is white so you can't see my white text. I'd suggest checking for iOS version and implementing different attributes based on each.

self.name
  • 2,341
  • 2
  • 17
  • 18
  • 1
    https://github.com/erica/iOS-6-Advanced-Cookbook/tree/master/C01%20-%20Device/02%20-%20UIDevice-Hardware This is a good library to use for checking just about everything about a device. Grab UIDevice-Hardware.h – Rob Oct 02 '13 at 06:12
4

Here's an example of using pickerView:viewForRow:forComponent:reusingView: in a way that honors the recycled views.

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UILabel *)recycledLabel {
    UILabel *label = recycledLabel;
    if (!label) { // Make a new label if necessary.
        label = [[UILabel alloc] init];
        label.backgroundColor = [UIColor clearColor];
        label.textAlignment = NSTextAlignmentCenter;
    }
    label.text = [self myPickerTitleForRow:row forComponent:component];
    return label;
}
Chris
  • 39,719
  • 45
  • 189
  • 235