Search code examples
iosswiftuigesturerecognizeruipickerview

I want user to select country only when he/she tapped on uipickerview in swift 3


I have created list of countries in UIPickerView and calling it in UItextField. Now, I want user to tap on UIPIckerView to select the country name. I did some research in stack overflow and found (surprisingly!!) there is no easy of doing it. I have written the below code for this purpose it is showing me an below error:

 Cannot convert value of type 'CGRect' to expected argument type 'CGFloat'

is there a easy way doing it .. it is very basic requirement should very straightforward; else, can someone help how to resolve the error I am getting when creating tapped function

below is my code

 class StudentSignUpViewController: UIViewController,UIScrollViewDelegate, UITextFieldDelegate,UIPickerViewDelegate,UIPickerViewDataSource, UIGestureRecognizerDelegate {




@IBOutlet weak var countryText: UITextField!
@IBOutlet weak var scrollView: UIScrollView!

///who are you option dropdown box
var picker = UIPickerView()

override func viewDidLoad() {
    super.viewDidLoad()

    //setting portrait
    AppUtility.lockOrientation(.portrait)

    //hide keyboard when click outside
    self.hideKeyboardWhenTappedAround()

    //hide keyboard when click on return

    self.countryText.delegate = self

    self.scrollView.delegate = self

    picker.delegate = self
    picker.dataSource = self
    self.countryText.inputView = picker

    let tap = UITapGestureRecognizer(target: self, action: #selector(pickerTapped))
    tap.cancelsTouchesInView = false
    tap.delegate = self
    picker.addGestureRecognizer(tap)

}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    AppUtility.lockOrientation(.portrait)

}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    AppUtility.lockOrientation(.all)
}


//*************************************************************** creating dropdown for country list ***************************************************************

let countries = NSLocale.isoCountryCodes.map { (code:String) -> String in
    let id = NSLocale.localeIdentifier(fromComponents: [NSLocale.Key.countryCode.rawValue: code])
    return NSLocale(localeIdentifier: "en_US").displayName(forKey: NSLocale.Key.identifier, value: id) ?? "Country not found for code: \(code)"
}

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

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


func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
{
    return self.countries[row];
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
    self.countryText.text = self.countries[row];
    self.countryText.endEditing(true)
}


func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true}

@objc func pickerTapped(tapRecognizer:UITapGestureRecognizer)
{
    if (tapRecognizer.state == UIGestureRecognizerState.ended)
    {
        let frame = CGRect.zero
        let rowHeight : CGFloat  = self.picker.rowSize(forComponent: 0).height
        let selectedRowFrame: CGRect = frame.insetBy(dx: self.picker.bounds, dy: (self.picker.frame.height - rowHeight) / 2.0 ) //Error: Cannot convert value of type 'CGRect' to expected argument type 'CGFloat'
        let userTappedOnSelectedRow = (selectedRowFrame.contains(tapRecognizer.location(in: picker)))
        if (userTappedOnSelectedRow)
        {
           self.picker.selectedRow(inComponent: 0)

        }
    }
}

}


Solution

  • As per apple standards, you should add toolbar to pickerview having a button done which will dismiss the pickerview. Selection is already being done by scrolling the pickerview row and keeping the selected row at the central segment. But if your requirement is very strict then you should create your own custom component