Search code examples
iosobjective-ciphoneuipickerview

How to connect UIPickerView options to individual pages


I just joined this site after looking very hard for an answer to my question and you guys seem to be amazing at what you do. I want to build a simple intro app for the iPhone. The problem I ran into is that I want to use a UIPickerView for choosing a variety of options, I have about 20 options in the pickerview. Next thing I want to do is to be able to open the next window when you click an option, I want to have individual windows for each of my options in the pickerview. Essentially I have a brand, then when you pick the brand by selecting it on the pickerview, you move on to the right accessories made for that brand. There are individual accessories made for each brand which is why I need a different new window for each. I already have my pickerview in place I just dont know how to proceed to the next step. Once I select an item on the pickerview by tapping, I want it to move to the corresponding next window. Thank you in advance for your help.


Solution

  • I'm going to assume that when declaring your UIPickerView, you've set the delegate to current view either in Interface Builder or done so in the code i.e. myPicker.delegate = self;. Also in your .h file, you have set up the controller such that it is analogous to myViewController: UIViewController<UIPickerViewDelegate>.

    You'll implement the following method and use the row argument to decide which view to show next. This method gets fired after a row is selected (and was wired to do so the moment you specified which class is the delegate of the picker view). Assuming you're using a navigationController, it could look something like:

    - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
        //For example, you can do a switch based on the row
        switch (row) {
             case 0:
                 [self.navigationController pushViewController:myFirstView animated:YES];
                 break;
             case 1:
                 [self.navigationController pushViewController:mySecondView  animated:YES];
                 break;
             // ..
             // ..
             case 19:
                 break;
             default:
            //...
        }
    }
    

    Note that if you declare a new variable (such as one of your view controllers) inside a case statement, you need braces { } inside the case statement in order to do so.

    Alternatively, if you don't want the event to fire automatically after a row is selected (for example, in case of the user accidentally selecting a row), you can create a button that the user presses to confirm the selection/proceed. Upon pressing the button, the button's target method could act according to the selected row in the picker. You can find the selected row with the following method call [myPicker selectedRowInComponent:0] (assuming your picker only has one column/"component").

    Good luck!

    Edits (after reading your follow-up questions):

    Assuming that SingleComponentPickerViewController.h is the view where you created your UIPickerView.

    SingleComponentPickerViewController.h:

    @interface SingleComponentPickerViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource>
    

    SingleComponentPickerViewController.m:

    In your viewDidLoad, (or wherever you created the pickerview), set the delegate:

    -(void) viewDidLoad {
        //...
        myPickerView.delegate = self;
        //...
        [super viewDidLoad];
    }
    

    To access your myPickerView variable in the above method, it will mean that your UIPickerView object has class scope or is a property.

    Also, have the action that is fired after the button press in this file.

    -(void)onButtonPress:(id)sender {
        //This gets the currently selected row from the picker
        //Again, assuming you have your picker as a property or class variable
        int row = [myPickerView selectedRowInComponent:0];
    
        //In your final version you need to use a condition to decide which view to show.
        if (row == 0) {
            AnotherView *anotherViewInstance = [[AnotherView alloc] init];
    
            //Show "anotherView"
            [self.navigationController pushViewController:anotherViewInstance animated:YES];
        }
        else if (row == 1) {
            AnotherView2 *anotherView2 = [[AnotherView2 alloc] init];
    
            //Show "anotherView"
            [self.navigationController pushViewController:anotherView2 animated:YES];
        }
        else if (row == 2) {
            AnotherView3 *anotherView3 = [[AnotherView3 alloc] init];
    
            //Show "anotherView"
            [self.navigationController pushViewController:anotherView3 animated:YES];
        }
        //...continue with the rest of your conditions here
    }
    

    If you are using Interface Builder, then you should change the return type from void to IBAction.

    SingleComponentAppDelegate.m

    Right now I'm assuming your App Delegate's didFinishLaunchingWithOptions looks something like this near the end:

    //....
    self.viewController = [[SingleComponentPickerViewController alloc] initWithNibName...];
    self.window.rootViewController = self.viewController;     
    [self.window makeKeyAndVisible];
    return YES;
    

    You want to modify it the window's rootViewController property to be set to a navigation controller, with your custom view controller inside of it. This way, you can easily push and pop views onto the screen.

    //...
    //Create your base view, similar (or even identically) to what was done earlier
    SingleComponentPickerViewController *myView = [[SingleComponentPickerViewController alloc] initWithNibName...]; 
    
    //Stick it inside a UINavigationController so you can push and pop views on top of it.
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:myView];
    
    //Assign that to the window's rootViewController, show it, and return
    self.window.rootViewController = nav;     
    [self.window makeKeyAndVisible];
    return YES;