swiftuipickerviewuipickerviewcontrolleruipickerviewdatasourceuipickerviewdelegate

Multiple UIPickerview Errors


I just wanna let you know that the version of Xcode that I'm working on is 7.1.1. Getting to the point, I have three Pickerviews as is shown in the image below. Main pickerview, left pickerview, and right pickerview.

The array of main pickerview has a group of names, and each name has a group of units, and the right and left pickers are supposed to have the same data. I have made a dictionary in order to sync those groups of units to where it belongs, but I could not do it.

I tagged the main Picker with 1, the left Picker with 2, and the right picker with 3. Also, all the pickers I have linked them with "dataSource" & "delegate".

http://s12.postimg.org/fj72kg29p/main_View.png


The main goal is:

I want when I pick a name i.e "Area" from the main picker its group must show or appear in the left and right pickers and so on.

I have done what I have done but I got the following error:

http://s1.postimg.org/523f3smwf/Screen_Shot_2015_11_27_at_12_39_20_AM.png

Here is my code:

import UIKit

class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate {

    @IBOutlet weak var mainPicker: UIPickerView!
    @IBOutlet weak var leftPicker: UIPickerView!
    @IBOutlet weak var rightPicker: UIPickerView!
    @IBOutlet weak var textFieldLeft: UITextField!
    @IBOutlet weak var textFielfRight: UITextField!
    @IBOutlet weak var equal: UILabel!

    //var mainPickerData = []
    var leftPickerData = []
    var rightPickerData = []

    var dataDict:NSMutableDictionary!
    var mainPickerData:NSArray!
    var leftRightPickerData:NSArray!

    //yourPicker.backgroundColor = UIColor(patternImage: UIImage(named: "back.jpg")!)


    override func viewDidLoad() {
        super.viewDidLoad()



        // Connect data:
        self.mainPicker.delegate = self
        self.mainPicker.dataSource = self

        self.leftPicker.delegate = self
        self.leftPicker.dataSource = self

        self.rightPicker.delegate = self
        self.rightPicker.dataSource = self

        let theWidth = view.frame.size.width
        let theHeight = view.frame.size.height

        mainPicker.center = CGPointMake(theWidth/2, theHeight/2 - 182.5)
        leftPicker.center = CGPointMake(theWidth/2 - 100, theHeight/2)
        rightPicker.center = CGPointMake(theWidth/2 + 100, theHeight/2)
        textFieldLeft.center = CGPointMake(theWidth/2 - 90, theHeight/2 + 110)
        textFielfRight.center = CGPointMake(theWidth/2 + 90, theHeight/2 + 110)
        equal.center = CGPointMake(theWidth/2, theHeight/2 + 110)



        let dataDict:NSMutableDictionary = ["Area":["Square Mile", "Square Yard", "Square Foot", "Square Inch", "Hectare", "Acre", "Square Kilometer", "Square Meter", "Square Centimeter", " Square Millimeter"]
            ,"Energy":["Btus", "Calories", "Ergs", "Foot-Pounds", "Joules", "Kilogram-Calories", "Kilogram-Meters", "Kilowatt-Hours", "Newton-Meters", "Watt-Hours"], "Length":["Mile", "Yard", "Foot", "Inch", "Kilometer", "Meter", "Centimeter", "Millimeter"], "Power": ["Btus/Minute", "Foot-Pounds/Min", "Foot-Pounds/Sec", "Horsepower", "Kilowatts", "Watts"], "Pressure": ["Pounds/Sqr Ft", "Pounds/Sqr In", "Atmospheres", "Bars", "In of Mercury", "Cm of Mercury", "Kilograms/Sqr Meter", "Pascals"], "Speed": ["Knots", "Miles/Hr", "Miles/Min", "Feet/Min", "Feet/Sec", "Kilometers/Hr", "Kilometer/Min", "Meters/Sec"], "Temperature": ["Celsius C˚", "Fahrenheit", "Kelvin"], "Time": ["Years", "Months", "Weeks", "Days", "Hours", "Minutes", "Seconds", "Millisconds", "Microseconds", " Nanoseconds"], "Volume": ["Cupic Feet","Cubic Meter", "Gallon (Imp)", "Gallon (US)", "Quart (US)", "Pint (US)", "Fluid Oz", "Cup", "Tablespoon", "Teaspoon", "Dram (US)", "Liter"], "Weight": ["Short Ton (US)","Long Ton (UK)", "Pound (U.S)", "Ounce (US)", "Stone", "Metric Ton", "Kilogram", "Gram"]]
        mainPickerData = dataDict.allKeys;
        leftRightPickerData = dataDict.objectForKey(mainPickerData.firstObject as! String) as! NSArray

        // Linking the textFields with the pickerViews.
        textFieldLeft.inputView = leftPicker;
        textFielfRight.inputView = rightPicker;


        }

    // The number of columns of data
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }

    // The number of rows of data
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {

        switch (pickerView.tag) {

        case mainPicker.tag:

            return mainPickerData.count

        case leftPicker.tag,rightPicker.tag:

            let currentSelectedIndex = mainPicker.selectedRowInComponent(0)
            leftRightPickerData = (dataDict.objectForKey(mainPickerData[currentSelectedIndex] as! String) as! NSArray)

            return leftRightPickerData.count;

        default:
            break;
        }
        return 0;
    }

    // The data to return for the row and component (column) that's being passed in
    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

        if leftPicker.tag == 1 {

            return leftPickerData[row] as? String

        }else {

            return rightPickerData[row] as? String

        }


    }

    // Catpure the picker view selection
    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        // This method is triggered whenever the user makes a change to the picker selection.
        // The parameter named row and component represents what was selected.

        if(pickerView.tag == 1 ){

            let currentSelectedIndex = mainPicker.selectedRowInComponent(0)
            leftRightPickerData = (dataDict.objectForKey(mainPickerData[currentSelectedIndex] as! String) as! NSArray)

            leftPicker.reloadAllComponents();
            rightPicker.reloadAllComponents();
        }

    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

        self.view.endEditing(true)

    }

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



}

Solution

  • Also in your func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? properly handle attributed text for all the pickers otherswise your code will crash. You just have define attributedTitle for mainPicker. Do it for others too like the following.Make changes as per your need.

    func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
    
        let titleData : String?
        if(pickerView.tag == mainPicker.tag){
            titleData = mainPickerData[row] as? String;
    
        }
        else{
    
            let currentSelectedIndex = mainPicker.selectedRowInComponent(0)
            leftRightPickerData = (dataDict.objectForKey(mainPickerData[currentSelectedIndex] as! String) as! NSArray)
    
            titleData = leftRightPickerData[row] as? String;
        }
    
        let myTitle = NSAttributedString(string: titleData!, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 15.0)!,NSForegroundColorAttributeName:UIColor.blueColor()])
        return myTitle;
    
    }