Is there any way to add UIPickerView into UIAlertController (Alert or ActionSheet) in Swift?

Hristo Atanasov picture Hristo Atanasov · Aug 28, 2014 · Viewed 47.5k times · Source

I'm totally new to swift (and iOS programming at all), but I started messing around with it (it wasn't a good idea when everything is still beta version :D). So I tried to figure it out by myself, but still nothing. Even tried to add subview containing picker without any success. So can any one help me?

Answer

Hristo Atanasov picture Hristo Atanasov · Nov 25, 2014

Well this is my final code which worked for me. It is a mix by a few ideas. The main reasons that I will accept my answer is that my code is in Swift, my code uses UIAlertController, my code is for picker. I want to thank to Jageen - my answer is based on his idea.

    func showPickerInActionSheet(sentBy: String) {
    var title = ""
    var message = "\n\n\n\n\n\n\n\n\n\n";
    var alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.ActionSheet);
    alert.modalInPopover = true;


    //Create a frame (placeholder/wrapper) for the picker and then create the picker
    var pickerFrame: CGRect = CGRectMake(17, 52, 270, 100); // CGRectMake(left), top, width, height) - left and top are like margins
    var picker: UIPickerView = UIPickerView(frame: pickerFrame);

    /* If there will be 2 or 3 pickers on this view, I am going to use the tag as a way
    to identify them in the delegate and datasource. /* This part with the tags is not required.
    I am doing it this way, because I have a variable, witch knows where the Alert has been invoked from.*/
    if(sentBy == "profile"){
        picker.tag = 1;
    } else if (sentBy == "user"){
        picker.tag = 2;
    } else {
        picker.tag = 0;
    }

    //set the pickers datasource and delegate
    picker.delegate = self;
    picker.dataSource = self;

    //Add the picker to the alert controller
    alert.view.addSubview(picker);

    //Create the toolbar view - the view witch will hold our 2 buttons 
    var toolFrame = CGRectMake(17, 5, 270, 45);
    var toolView: UIView = UIView(frame: toolFrame);

    //add buttons to the view
    var buttonCancelFrame: CGRect = CGRectMake(0, 7, 100, 30); //size & position of the button as placed on the toolView

    //Create the cancel button & set its title
    var buttonCancel: UIButton = UIButton(frame: buttonCancelFrame);
    buttonCancel.setTitle("Cancel", forState: UIControlState.Normal);
    buttonCancel.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal);
    toolView.addSubview(buttonCancel); //add it to the toolView

    //Add the target - target, function to call, the event witch will trigger the function call
    buttonCancel.addTarget(self, action: "cancelSelection:", forControlEvents: UIControlEvents.TouchDown);


    //add buttons to the view
    var buttonOkFrame: CGRect = CGRectMake(170, 7, 100, 30); //size & position of the button as placed on the toolView

    //Create the Select button & set the title
    var buttonOk: UIButton = UIButton(frame: buttonOkFrame);
    buttonOk.setTitle("Select", forState: UIControlState.Normal);
    buttonOk.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal);
    toolView.addSubview(buttonOk); //add to the subview

    //Add the tartget. In my case I dynamicly set the target of the select button
    if(sentBy == "profile"){
        buttonOk.addTarget(self, action: "saveProfile:", forControlEvents: UIControlEvents.TouchDown);
    } else if (sentBy == "user"){
        buttonOk.addTarget(self, action: "saveUser:", forControlEvents: UIControlEvents.TouchDown);
    }

    //add the toolbar to the alert controller
    alert.view.addSubview(toolView);

    self.presentViewController(alert, animated: true, completion: nil);
}

func saveProfile(sender: UIButton){
    // Your code when select button is tapped

}

func saveUser(sender: UIButton){
    // Your code when select button is tapped
}

func cancelSelection(sender: UIButton){
    println("Cancel");
    self.dismissViewControllerAnimated(true, completion: nil);
    // We dismiss the alert. Here you can add your additional code to execute when cancel is pressed
}

// returns number of rows in each component..
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
    if(pickerView.tag == 1){
        return self.profilesList.count;
    } else if(pickerView.tag == 2){
        return self.usersList.count;
    } else  {
        return 0;
    }
}

// Return the title of each row in your picker ... In my case that will be the profile name or the username string
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
    if(pickerView.tag == 1){

            var selectedProfile: Profiles = self.profilesList[row] as Profiles;
            return selectedProfile.profileName;

    } else if(pickerView.tag == 2){

            var selectedUser: Users = self.usersList[row] as Users;
            return selectedUser.username;

    } else  {

        return "";

    }

}

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    if(pickerView.tag == 1){
            var choosenProfile: Profiles = profilesList[row] as Profiles;
            self.selectedProfile = choosenProfile.profileName;
    } else if (pickerView.tag == 2){
            var choosenUser: Profiles = usersList[row] as Users;
            self.selectedUsername = choosenUser.username;
    }

}