0

I'm trying to create a UIPickerView programmatically and display it's rows within an action sheet. However, nothing seems to be working. Here is a simplified example of similar non-working code:

import UIKit

class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {

    let array = ["one","two","three","four","five"]
    var controller: UIAlertController?
    var pickerView = UIPickerView(frame: CGRectMake(0, 15, 304, 0))

    @IBOutlet weak var button: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        controller = UIAlertController(title: "Choose Category", message: "\n\n\n\n\n\n\n\n", preferredStyle: .ActionSheet)
        let doneAction = UIAlertAction(title: "Done", style: .Default, handler: nil)
        controller!.addAction(doneAction)

        pickerView.delegate = self
        pickerView.dataSource = self
    }

   @IBAction func buttonPressed(sender: AnyObject) {
        controller!.view.addSubview(self.pickerView)
        self.presentViewController(controller!, animated: true, completion: nil)
    }

    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }

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

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

    func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView {
        let view = UIView(frame: CGRectMake(0, 0, 100, 70))

        let label = UILabel(frame: CGRectMake(50, 5, 100, 60))
        label.text = array[row] as String

        view.insertSubview(label, atIndex: 1)

        return view
    }
}

When the button is pressed, this is the output:

Screenshot of a UIAlertController being displayed on an iPhone 4S

As you can see, the action sheet is not being populated with the array values. This was all working properly before the I upgraded to iOS 9 and Swift 2.0. I've used print to make sure the pickerView methods are being called which they are and even using print to check the value of label and view and they are there. Can anyone either guide me in a direction or explain what is causing this to not be displayed?

Also: Another funky thing is how these methods are being called. If I press the button once, this is the order of every method call that happens:

numberOfComponentsInPickerView:
numberOfComponentsInPickerView:
rowHeightForComponent:
rowHeightForComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfComponentsInPickerView:
numberOfRowsInComponent:
viewForRow:
viewForRow:
numberOfComponentsInPickerView:
rowHeightForComponent:
rowHeightForComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
numberOfRowsInComponent:
viewForRow:
viewForRow:
viewForRow:
viewForRow:
viewForRow:
Aaron
  • 6,466
  • 7
  • 37
  • 75
  • Where's the code that adds the picker view to the alert? Where's the code that presents the alert? – rmaddy Sep 21 '15 at 23:01
  • I forgot that line but I just edited and added it in. The adding is taking place in the buttonPressed action – Aaron Sep 21 '15 at 23:05
  • Try increasing the `y` value of the picker view's origin until it appears. Of course do you realize that what you are doing isn't supported, right? The docs for `UIAlertController` clearly state: *The view hierarchy for this class is private and must not be modified.* – rmaddy Sep 21 '15 at 23:08
  • @rmaddy thank's I'll try that right now. What would you say is going on with all of the calls that I added at the bottom? – Aaron Sep 21 '15 at 23:11
  • It means your picker is working. It's just not in the right place. But again, don't do it. Adding a picker view (or anything else) to a `UIAlertController` isn't supported and anything you do to make it work is a hack that can break with any new iOS version. – rmaddy Sep 21 '15 at 23:13
  • Ok, thanks for the input. I'm more curious as to what would make it just stop showing up in my beta app version. I'd like to at least get it working to get an update out while I fix it for real like you said. I changed the "y" value of var pickerView = UIPickerView(frame: CGRectMake(0, 15, 304, 0)) and changed the 15 to 45, 85, 125, 185, and 285 and none of those show anything. – Aaron Sep 21 '15 at 23:15

1 Answers1

2

You're not supposed to modify the view hierarchy of a UIAlertController. Even if you could get it to work that way, you risk Apple breaking it anytime there's an update and you'd have to keep finding new workarounds to make it work. You may want to consider putting your picker in a view controller and presenting it as a UIModalPresentationPopover. If you're using it with a responder subclass like a text field or a custom one you make, you can also make a view that looks like the action sheet with a picker and set it as the inputView of the responder.

Ahmed Hamed
  • 504
  • 1
  • 3
  • 11