Make App Pie

Training for Developers and Artists

Swift Swift: Formatting a UIPickerView

[Updated to Swift 2.0/iOS9.0 9/15/15]

I’ve posted on UIPickerViews before, but in the comments for that post, I got a question that needed an answer so big, it was worth a new post.

UIPickerViews are those spinning wheel slot machine type controls. For a variety of reasons I went into in the earlier post they are not as common as other  controls in iOS. The reason I’ll focus on here is the lack of properties for a UIPickerView. It relies heavily on delegates. In this lesson we’ll look at some of those delegate methods.

Setting Up a Demo

I debated just having people go to the UIPickerView lesson, and start with that, but decided it would be simpler to start with a single-component picker view instead of the double component in that lesson. I will go through the setup quickly and if you  are not understanding something, I’d suggest clicking here and doing that lesson first.

Make a new project with Command-Shift-N, under iOS make a single view project named SwiftUIPickerFormatted. Drag a label and a picker view onto the view controller on the storyboard.
Screenshot 2014-10-20 12.11.21

Open the Assistant editor, and control-drag from the label to make an outlet named myLabel. Control-drag from the picker view and make an outlet named myPicker. Close the assistant editor and go to the ViewController.swift file. Clean up the code, then add the data for the picker view there so it looks like this:

class ViewController: UIViewController {

    @IBOutlet weak var myPicker: UIPickerView!
    @IBOutlet weak var myLabel: UILabel!
    let pickerData = ["Mozzarella","Gorgonzola","Provolone","Brie","Maytag Blue","Sharp Cheddar","Monterrey Jack","Stilton","Gouda","Goat Cheese", "Asiago"]
    override func viewDidLoad() {
        super.viewDidLoad()
        myPicker.dataSource = self
        myPicker.delegate = self
    }

}

UIPickerView needs a delegate and a data source.  In the viewDidLoad above we set both the delegate and dataSource to to self so we can add the required methods here. Change the class declaration to this:

class ViewController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate {

You will get the classic

Type 'ViewController' does not conform to protocol 'UIPickerViewDataSource'

error.  Xcode is whining at you to add some required methods for the protocol. The two methods are in the data source. Add these towards the bottom of your code:

//MARK: - Delegates and data sources
    //MARK: Data Sources
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return pickerData.count
    }

We have only one component for the picker view so we return a literal 1. Using .count we get the number of rows from the data. We have some optional methods to use in UIPickerViewDelegate. Add these below the Data Source methods:

 //MARK: Delegates
    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return pickerData[row]
    }

    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        myLabel.text = pickerData[row]
    }

The first method places the data into the picker and the second selects and displays it in the label. You can now build and run and spin the wheel a bit:
Screenshot 2014-10-21 07.38.20

Formatting Picker Views with Attributed Strings

Now that we have set up a picker view, we might want a different font or color. There is a method which uses attributed strings.  Add this under the code we already have:


    func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
        let titleData = pickerData[row]
        let myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 15.0)!,NSForegroundColorAttributeName:UIColor.blueColor()])
        return myTitle
    }

If you are not familiar with attributed Strings,  click here and check out my earlier post on how to use them. This should change the font to blue 15 point Georgia given the attributed string we have. Build and run.
Screenshot 2014-10-21 07.39.05
We do get blue, but no font change. You can change many attributes of a string. You cannot change the font in  attributed text  for picker views.

Using UIViews to Format the Picker

There is one more very powerful method for displaying something on a UIPickerView. There is a method in the delegate to display a UIView. One subclass of UIView is a UILabel. So we could make a label and have the delegate method return a formatted UILabel. Add this example using attributed strings to the code we have so far:

    func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView {
        let pickerLabel = UILabel()
        let titleData = pickerData[row]
        let myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 26.0)!,NSForegroundColorAttributeName:UIColor.blackColor()])
        pickerLabel.attributedText = myTitle
       return pickerLabel
    }

Build and run.

Screenshot 2014-10-21 07.40.24

We get a change of font, but it is left justified. I went back to a black font for our next addition. With a UILabel in this delegate method, you can use all the properties of a UILabel instead of attributed text. I could use text and font property instead of attributed text. I’ll change textAlignment to .Center and I’ll add a colored background to the label by adding this to the delegate method.

         //color  and center the label's background
        let hue = CGFloat(row)/CGFloat(pickerData.count)
        pickerLabel.backgroundColor = UIColor(hue: hue, saturation: 1.0, brightness:1.0, alpha: 1.0)
        pickerLabel.textAlignment = .Center
        return pickerLabel

As I discussed in my color post on hues, this is a simple example to do multiple colors. Line two takes the current element and divides it by the number of elements in our array. Since both are type Int, I cast them to CGFloat before I do the division. This will be a  CGFloat between 0 and 1, which I use as my hue in assigning a color. Build and run:
Screenshot 2014-10-21 07.41.19

You should be a bit more conservative with memory using this. A better way to write this is:

func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView {
        var pickerLabel = view as! UILabel!
        if view == nil {  //if no label there yet
            pickerLabel = UILabel()
            //color the label's background
            let hue = CGFloat(row)/CGFloat(pickerData.count)
            pickerLabel.backgroundColor = UIColor(hue: hue, saturation: 1.0, brightness: 1.0, alpha: 1.0)
        }
        let titleData = pickerData[row]
        let myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 26.0)!,NSForegroundColorAttributeName:UIColor.blackColor()])
        pickerLabel!.attributedText = myTitle
        pickerLabel!.textAlignment = .Center
        return pickerLabel

    }

This way we check if the label is already created before creating a new one.

Sizing the UIPickerView

You’ll notice that things seem a little squeezed in using the label. One way of fixing this is two more delegate methods: rowHeightForComponent and widthForComponent. Add this to increase the spacing between cells in the picker view:

 func pickerView(pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
        return 36.0
    }

If you build and run, you get this:

Screenshot 2014-10-21 07.42.04

While in a single component, it is not so important, if you have multiple components you can change the width of each spinner as well. Let’s make the component smaller. Add this code:

 func pickerView(pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
        return 200
    }

We are making all the components the same here, since we only have one. We could use the component parameter to identify the component and have different lengths for each one. Build and run.

Screenshot 2014-10-21 07.43.00

That is a few of the things you could do with a UIPickerView. There are a lot more, and since it accepts a UIView anything is possible for a user interface. Apple does recommend in the Human Interface Guide that UITableViews are a better option if you want to get complex. But the UIPickerView does have some very good uses, limited by your creativity.

The Whole Code

//
//  ViewController.swift
//  SwiftUIPickerFormatted
//
//  Created by Steven Lipton on 10/20/14.
//  Copyright (c) 2014 MakeAppPie.Com. All rights reserved.
//  Updated to Swift 2.0  9/15/15 SJL

import UIKit

class ViewController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate {
    
    @IBOutlet weak var myPicker: UIPickerView!
    @IBOutlet weak var myLabel: UILabel!
    let pickerData = ["Mozzarella","Gorgonzola","Provolone","Brie","Maytag Blue","Sharp Cheddar","Monterrey Jack","Stilton","Gouda","Goat Cheese", "Asiago"]
    override func viewDidLoad() {
        super.viewDidLoad()
        myPicker.delegate = self
        myPicker.dataSource = self
        
    }
    //MARK: - Delegates and data sources
    //MARK: Data Sources
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return pickerData.count
    }
    //MARK: Delegates
    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return pickerData[row]
    }
    
    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        myLabel.text = pickerData[row]
    }
    
    func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
        let titleData = pickerData[row]
        let myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 26.0)!,NSForegroundColorAttributeName:UIColor.blueColor()])
        return myTitle
    }
 /* less conservative memory version
    func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView {
        let pickerLabel = UILabel()
        let titleData = pickerData[row]
        let myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 26.0)!,NSForegroundColorAttributeName:UIColor.blackColor()])
        pickerLabel.attributedText = myTitle
        //color  and center the label's background
        let hue = CGFloat(row)/CGFloat(pickerData.count)
        pickerLabel.backgroundColor = UIColor(hue: hue, saturation: 1.0, brightness:1.0, alpha: 1.0)
        pickerLabel.textAlignment = .Center
        return pickerLabel
    }
  */
    
/* better memory management version */
    func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView {
        var pickerLabel = view as! UILabel!
        if view == nil {  //if no label there yet
            pickerLabel = UILabel()
            //color the label's background
            let hue = CGFloat(row)/CGFloat(pickerData.count)
            pickerLabel.backgroundColor = UIColor(hue: hue, saturation: 1.0, brightness: 1.0, alpha: 1.0)
        }
        let titleData = pickerData[row]
        let myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 26.0)!,NSForegroundColorAttributeName:UIColor.blackColor()])
        pickerLabel!.attributedText = myTitle
        pickerLabel!.textAlignment = .Center
        
        return pickerLabel
        
    }
    
    func pickerView(pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
        return 36.0
    }
    // for best use with multitasking , dont use a constant here.
    //this is for demonstration purposes only.
    func pickerView(pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
        return 200
    }
    
    
    
}

63 responses to “Swift Swift: Formatting a UIPickerView”

  1. Fantastic!

  2. Just one question:
    Whenever I set the delegates to self in the viewDidLoad method, the program fails. Any suggestions?

    1. Nevermind. I had called a numberOfComponents(1) method on it before, causing the error.

  3. Do you have any suggestions for keeping the UIPickerView very short so as to only show one component until the picker is clicked on? Without compressing the font?

    1. UIPickerViews are really meant to stay pretty static in terms of size (one reason they are not that popular). They really aren’t “clicked on” which is why they have delegates. The Apple Human Interface Guide frowns (uses the term “As much as possible”) on having them conditionally visible, so trying to do what you are doing could get your app rejected.

    2. I used this tutorial to hide the row of a date picker until the above row was selected. http://manenko.com/2014/12/19/put-uidatepicker-inside-static-uitableview/

  4. Hi, I have problem in chapter “Using UIViews to Format the Picker”. When I finish “let myTitle = NSAttributedString…” line, xcode tells me ” Cannot invoke ‘init’ with an argument list of type ‘(string:string, atributes:$T9’ “. I don’t know what I should do. Thanks

    1. There was a change in Swift from the time I wrote this and the current release of XCode. I’m working on a solution now. Apparently there some changes to optionals in attributed text.

      1. ok, thank you. btw nice tutorials.

      2. Thank you for the compliment. And I have a solution.

        It turns out that in the latest version of Swift the UIFont is now optional. In order to put it in the attributes dictionary correctly you have to unwrap the optional. So the code now reads:

        var myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 15.0)!,NSForegroundColorAttributeName:UIColor.blueColor()])

        Just add an exclamation point after the UIFont initializer, and your error should disappear.

        I updated the tutorial for this change, and I now have to go to the attributed string one and change it there too. Thank you for catching this error.
        Steve

  5. thank you so much for the tutorial! I’d been pulling hair for a couple of weeks!

    1. You are welcome. Glad it solved a problem.

  6. This is a quite good blog/tutorial.

    I have worked out how to add and format additional components. Seems an un-intuitive approach to have to use if constructs. Is there an alternative/better approach?

    I have not been able to make a component loop e.g. the UIDatePicker loops the day, hours and minute components. Can this behaviour be emulated with UIPickerView?

    Thanks!

  7. In what circumstances would view == nil ? (line 50)
    if view == nil { //if no label there yet

    Thanks.
    -u

    1. When there is no label in that row yet. The app created a brand new picker view most likely, or cleared the contents of this row. Only when the label is empty does the delegate create a label, otherwise it just reads it. This is more efficient than creating a new label every time you access a row.

  8. Thanks for the answer, but it does not easily make sense to me, you write, “Only when the label is empty does the delegate create a label, otherwise it just reads it.“ If a label is empty, then it (the label) exists, and surely it can only be the text object that does not exist if a label is empty? However, I do not think this is what you intend. I think you are intending the creation of views. So how many views are needed? The code appears to work just as well without if view == nil, and I tried adding a flag or two, to try and see what is happening. There seems to be some correlation between the number of items in the pickerData array and the number of times a view is instantiated up to 10 that is, without making any picker selection(s).

    1. I should have used view there instead of label, referring to the parameter view. The line

       if view == nil 

      is part of a delegate that configures a row for a picker. In this delegate it configures a UIVIew for a certain row to display. You are correct you don’t need an if clause.. As I explained in the text, the five-line version above it:

      func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView {
          let pickerLabel = UILabel()
          let titleData = pickerData[row]
          let myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 26.0)!,NSForegroundColorAttributeName:UIColor.blackColor()])
          pickerLabel.attributedText = myTitle
      }
      

      works perfectly fine. But it makes the label every time you display the label. That takes time and memory to do. What I did was make the label once, the first time the row of the pickerView gets displayed. It is a form of lazy instantiation, which is just a good habit to have. It conserves processor power and memory.

      All the if statement does is create the UILabel once and make it the view for the row for the entire life of the UIPickerView.Before the first time the UIPickerview calls the delegate for a specific row. If in that row there is no UIView, the value of the parameter view is nil. I use that to make sure I only create the label once, no matter how many times this delegate gets called. Technically the only thing that was needed in the if block was the creation of a label – or I could make everything in the if clause.

      The number of views come from another delegate, whihc is a required delegate.

      func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
              return pickerData.count
      }
      

      So yes there is a very direct correlation between the number of views and the number of elements of pickerData That’s where we got it from.

  9. The third example you say, “makes a label every time you display the label” (sic), and that example 4 makes the label once, no matter how many times the delegate gets called. Although I get lazy instantiation, I don’t see this. Surely there are at least the same number of label views created, as there are labels visible, and maybe a couple of spares too, unless that is there is some other wizardry at work when building the graphic?

    The correlation between elements and calls isn’t what I may have anticipated. The number of calls made ranges between 4 and 10 depending upon the number of elements, where 1 element generates 4 calls, and 2 elements generates 7. 3 elements generates 8 calls and so on to 5 elements, which generates the maximum of 10 calls.

    I observe no difference in the delegate call pattern when comparing the two versions.

  10. Then don’t use the if. I got good results in Instruments. I’ll trust my data and practices, you can trust yours. I’ll call this session over.

  11. How do you make the UIPickerView wrap?

    1. Use a UILabel that wraps as your view.

    2. As a follow up to what I said yesterday, Haven’t tried this, but modify the code above like this:

      func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView {
          let pickerLabel = UILabel()
          pickerLabel.numberOfLines = 2
          pickerLabel.lineBreakMode = .ByWordWrapping
          let titleData = pickerData[row]
          let myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 26.0)!,NSForegroundColorAttributeName:UIColor.blackColor()])
          pickerLabel.attributedText = myTitle
         return pickerLabel
      }
      
      1. Awesome, thanks. I’ll give this a try as it is something else I wanted to know. What I’m looking for (sorry I wasn’t clear before) is how can you make the UIPickerView spin continuously (wrapping around)? Does that make sense?

      2. Oops. Soory I didnt understand. I really don’t know the answer to that question.

      3. No worries. You answered a question I did want to know, but forgot to ask. Thanks for the help. If I figure it out, I’ll post solution here. Thanks again!

  12. Yep I understand now and I really don’t know how you could get the delegate to point back to the beginning of the data when you reach the end.

    1. I’ve done it in Objective-C, but don’t know Objective-C that well {barely} so I don’t know how to convert it to Swift.

      1. I have an idea. Write out the objective-c here . I’ll do a post about converting one to the other. .

      2. Here’s the .h:

        //
        // ViewController.h
        // UIPickerViewWrapShake
        //

        #import

        @interface ViewController : UIViewController

        @property (nonatomic, strong) NSArray *produceArray;

        @property (nonatomic, strong) IBOutlet UIPickerView *picker;

        @property (nonatomic, strong) IBOutlet UILabel *myLabel;

        – (IBAction)shakeButton:(UIButton *)sender;

        @end

        Here’s the .m:
        //
        // ViewController.m
        // UIPickerViewWrapShake
        //

        #import “ViewController.h”

        @interface ViewController ()

        @end

        @implementation ViewController

        @synthesize produceArray;
        @synthesize picker;

        @synthesize myLabel;

        – (IBAction)shakeButton:(UIButton *)sender
        {

        [picker selectRow:(arc4random() % [self pickerView:picker numberOfRowsInComponent:0]) inComponent:0 animated:YES];

        [picker selectRow:(arc4random() % [self pickerView:picker numberOfRowsInComponent:0]) inComponent:1 animated:YES];

        [picker selectRow:(arc4random() % [self pickerView:picker numberOfRowsInComponent:0]) inComponent:2 animated:YES];

        }

        – (void)viewDidLoad
        {
        [super viewDidLoad];

        self.produceArray = [[NSArray alloc] initWithObjects:
        @”apple”
        ,@”watermelonj khguygjgljkhlkh”
        ,@”banana”
        ,@”pear”
        ,@”coconut”
        ,@”orange”
        ,@”pineapple”
        ,@”tomato”
        ,@”cucumber”
        ,@”pickle”
        ,@”pumpkin”
        ,@”cumquat”
        ,@”avocado”
        ,@”lettuce”
        ,@”Kale”
        ,@”spinach”
        ,nil];

        self.picker.dataSource = self;
        self.picker.delegate = self;
        }

        – (void)didReceiveMemoryWarning
        {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
        }

        // returns the number of ‘columns’ to display.
        – (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
        {
        return 3; //number of columns
        }

        // returns the # of rows in each component..
        – (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent: (NSInteger)component
        {
        //return [self.produceArray count]; //number of rows
        return ([self.produceArray count] * 3); //number of rows * 3 (for wrap)

        }

        -(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
        {

        //return [self.produceArray objectAtIndex:row];
        return [self.produceArray objectAtIndex:(row % [self.produceArray count])]; // for wrap using (row % [self.produceArray

        }

        // enable custom font and wrapping for component object
        – (UIView *)pickerView:(UIPickerView *)pickerView
        viewForRow:(NSInteger)row
        forComponent:(NSInteger)component
        reusingView:(UIView *)view
        {
        UILabel* tView = (UILabel*)view;

        if (!tView){

        tView = [[UILabel alloc] init];

        // Setup label properties – frame, font, colors etc
        tView.minimumScaleFactor = .1f;
        tView.adjustsFontSizeToFitWidth = YES;
        tView.numberOfLines = 1; // 1 = use with adjustFontSizeToFitWidth; 0 = use as many lines as needed, will wrap

        } // if (!tView){

        // Fill the label text with the array row
        //tView.text = [self.produceArray objectAtIndex:row];
        tView.text = [self.produceArray objectAtIndex:(row % [self.produceArray count])]; // for wrap using (row % [self.produceArray count])

        return tView;
        }

        – (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
        {

        //we want the selection to always be in the SECOND set (so that it looks like it has stuff before and after)
        if (row = (2 * [self.produceArray count]) ) {
        row = row % [self.produceArray count];
        row += [self.produceArray count];
        [pickerView selectRow:row inComponent:component animated:NO];
        }

        }

        @end

      3. Thanks for your help!! (not sure how to post storyboard… ) After posting above, I didn’t think I could have posted a link to create a GitHub repository for it. I’m trying to figure out how to do that.

      4. I have the worst luck with github. no worries. BUt this is what it look like. with a lot less code that what you gave me. What you gave me is more versatile and you could spin infinitely, but if you are not going to spin the dial 1000 times, the code I’m working on works just great.
        Screenshot of a version of app

      5. That’s great! The datasets I have in mind are less than 1000. Does it spin manually, with a button and/or shake? Thanks again for your help! I’m sooooo glad I found your site!

      6. This is a simple manual version. I’ll leave it you to get fancy.

      7. OK, great. Thanks again for your help!

      8. Thanks so much! I’ll take a look at it. Again, I really appreciate your help!

  13. How to change say “Brie” text to green when selected. All other picker titles remaining black and “Brie” reverting to black when not selected?
    Thanks

  14. Great tutorial. Is there a way to make only selected rows a selected color. I have a multi component picker and based on the selection in component 1 I would like to change a row (not necessarily the selected ones) to green in component 2.

    1. Only one I could think of is use another array of UIColor corresponding to your second component to set colors on the second component.

  15. Thanks for the reply. I have tried quite a bit without luck. I was hoping to change let’say the color of the font for just item 2 row 6. I tried attributed text but somehow everything ends up changing all rows.

    1. You can use similar code to the gradient background I demonstrate above the difference either: 1) use an if statement to turn the one you want to the color or as I metioned 2) maintain an array of UIColor. In both cases change the code I have to set to UIColor to the proper color, instead of computing one. LIke tableviews this may mean you’ll have to reload the picker every color change. While I dont know you applcation, I’m not sure putting a color on something you can’t see most of the time is good UI. A label is lot easier, or “freezing” the picker component by making the selected row the only row of the component.

      1. I think you are bringing me on the right track with the if statement. I have to try. My picker is complex in a way. It has 4 items. I have a picker with item 1 that has rows from a to z and item 2 with rows from 1 to 17. I have the same for item 3 and item 4. When I select “a” and “1” in resp. Item 1 and 2 then I want to select “g” and “6” in item 3 and item 4 and give them a selected color. On top of that there will be multiple rows in item 3 and 4 that will get that same color to show possible “matches”. Is there any way to add a screenshot to the post to explain?

      2. i think you got the idea of what you want to and need to do. No need.

  16. […] one.  I spent a bunch of time trying to figure out where my errors were.  I followed this example pretty closely but still was confused on why it wasn’t working.  After quite a while of […]

    1. Hate when that happens — and it happens a lot. Nice app.

  17. in func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {} delegate, I was able to change font color, but the font size and font style of the label in pickerview dont change? any other workarounds? thanks! great blog btw

    1. comment out one of the delegates.

    2. You cannot change the font for attributed text in a UIPickerView. Add a label to the picker view as described in the demo.

      1. Thanks, I used picker view and it works properly but I’m using two components, I was able to return both of my datasource to both components but its throwing “array out of range” when I try to selecting the values back and forth. It would be nice to have a post about pickerview with multiple components. :P

  18. great tutorial! It helped me alot setting up my picker.

    Question;
    Why u comment @ setting the width of the component:
    // for best use with multitasking , dont use a constant here.
    //this is for demonstration purposes only.

    This is when u have different strings with different lengths or something, right? Picker will not display when the length of the string is longer then the constant u set?

    (I hope my question can be clearly understood….)

    1. There is a long answer which will be a post sometime in October. The short answer is you have to fully implement size classes and autolayout in order to use your app in Mutitasking on an iOS9 iPad. You want nothing that’s a constant for a dimention.

      1. Ok, tx for the answer. And I will look for the long answer in Oktober.

  19. Hello to everybody, I’m a new in swift and xcode as well, Im stacked in connection pickerview to attribute in core data (want to show all cells in pickerview) I cant find nothing in net, could somebody give me an example or link how to do that.
    Thanks in advance.

    1. if you are new, you shouldn’t really be messing with core data. You are better off with a simple text file or xml for image data anyway.

  20. Somebody got the “func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?” to work in Swift 3?

    1. I’ll update this post sometime this week.

  21. great tutorial sir but I need a picker with seven components that rotate horizontally not vertically and my requirement is that the text of pickers should change as in default picker do. I have been trying on it more than 3 days but I did’t get a way and third party as well

    1. You’ll have to write your own scroll views for that.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: