UIPickerView delegate not called in a subview - ios

I have a simple iOS app that uses UISegmentedControl to switch between two tabs.
In ViewController.swift:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var segment: UISegmentedControl!
#IBOutlet weak var viewContainer: UIView!
var searchView: UIView!
var favView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
searchView = SearchViewController().view
favView = FavoriteViewController().view
viewContainer.addSubview(favView)
viewContainer.addSubview(searchView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func segmentChange(_ sender: UISegmentedControl) {
switch sender.selectedSegmentIndex{
case 0:
viewContainer.bringSubview(toFront: searchView)
break
case 1:
viewContainer.bringSubview(toFront: favView)
break
default:
break
}
}
}
And in the first tab, I have a UIPickerView as input of a Textfield.
import UIKit
class SearchViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var keywordField: UITextField!
#IBOutlet weak var categoryField: UITextField!
#IBOutlet weak var distanceField: UITextField!
#IBOutlet weak var locationField: UITextField!
var cgpicker = UIPickerView()
let categories = ["Default", "Airport", "Amusement Park", "Aquarium", "Art Gallery", "Bakery", "Bar"]
override func viewDidLoad() {
super.viewDidLoad()
cgpicker.delegate = self
cgpicker.dataSource = self
categoryField.inputView = cgpicker
categoryField.text = categories[0]
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
print("picker working")
return categories.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return categories[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
categoryField.text = categories[row]
categoryField.resignFirstResponder()
}
}
However, when I click the Textfield, the PickerView doesn't display data. In fact the delegate and datasource is not called since the "print" is never called. However the same code is working fine in a simple UIView app. I cannot find any solution related to this problem.
UIPickerView not showing data

The problem is with the viewDidLoad of your ViewController class.
You are not creating the container view controller properly. The primary issue preventing the picker from working is that your SearchViewController has no strong reference to it when viewDidLoad finishes so the picker in SearchViewController becomes nil.
Update the ViewController viewDidLoad to something like this:
override func viewDidLoad() {
super.viewDidLoad()
let searchVC = SearchViewController()
searchView = searchVC.view
addChildViewController(searchVC)
// Should set searchView frame or constraints
viewContainer.addSubview(searchView)
searchVC.didMove(toParentViewController: self)
let favVC = FavoriteViewController()
favView = favVC.view
addChildViewController(favVC)
// Should set favView frame or constraints
viewContainer.addSubview(favView)
favVC.didMove(toParentViewController: self)
}

This because you not load picker
you should have reference to SearchViewController not reference to its View
ViewController:
class ViewController: UIViewController {
#IBOutlet weak var segment: UISegmentedControl!
#IBOutlet weak var viewContainer: UIView!
var searchController: SearchViewController!
var favController: FavoriteViewController!
override func viewDidLoad() {
super.viewDidLoad()
searchController = SearchViewController()
favController = FavoriteViewController()
viewContainer.addSubview(searchController.view)
viewContainer.addSubview(favController.view)
searchController.loadPickerView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func segmentChange(_ sender: UISegmentedControl) {
switch sender.selectedSegmentIndex{
case 0:
viewContainer.bringSubview(toFront: searchController.view)
searchController.loadPickerView()
break
case 1:
viewContainer.bringSubview(toFront: favController.view)
break
default:
break
}
}
}
Add loadPickerView func to SearchViewController
func loadPickerView() {
cgpicker.delegate = self
cgpicker.dataSource = self
self.textFieldUserName.inputView = cgpicker
textFieldUserName.text = categories[0]
}

Related

Issue updating UIPickerView in Swift with user inputted data into an array

I'm writing a simple fitness app that allows the user to add user profiles which are displayed in a UIPickerView, and when selected, is entered into the profileField label on the main ViewController. The pickerView uses an array of Profile objects as its data source and displays the name of the profile in the picker. I have it set up to where the user clicks a button on the main ViewController and is segued to the AddProfileViewController where they input the necessary requirements to create a profile. When they hit submit the information successfully gets appended to the profileNames array but the pickerView does not show any changes when the user clicks back on it. I have tried using pickerView.reloadAllComponents() and pickerView.reloadComponent(1) to no success.
I am on Xcode Version 12.4 (12D4e)
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource
{
#IBOutlet weak var profileField: UITextField!
#IBAction func didTapEnter(_ sender: Any)
{
}
#IBAction func didTapNewProfile(_ sender: Any)
{
}
//these are pre-populated values in this array
var profileNames: [Profile] =
[
Profile("Brandon", 2, 120, 20, "Male"),
Profile("G", 2, 100, 20, "Male"),
Profile("K", 1.6, 111, 19, "Male"),
Profile("F", 2.1, 95, 20, "Male"),
Profile("J", 1.89, 97.5, 21, "Male")
]
var pickerView = UIPickerView()
override func viewDidLoad()
{
super.viewDidLoad()
pickerView = UIPickerView()
pickerView.delegate = self
pickerView.dataSource = self
profileField.inputView = pickerView
profileField.textAlignment = .center
profileField.placeholder = "Enter Profile"
}
func numberOfComponents(in pickerView: UIPickerView) -> Int
{
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
{
return profileNames.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
{
return profileNames[row].name
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
profileField.text = profileNames[row].name
profileField.resignFirstResponder()
}
func profileSubmit(_ data: Profile)
{
profileNames.append(data)
pickerView.reloadComponent(1) //This does not seem to do anything for me
}
}
class AddProfileViewController: UIViewController, UINavigationControllerDelegate
{
#IBOutlet weak var nameTextField: UITextField!
#IBOutlet weak var weightTextField: UITextField!
#IBOutlet weak var heightTextField: UITextField!
#IBOutlet weak var ageTextField: UITextField!
#IBOutlet weak var sexTextField: UITextField!
let main: ViewController? = nil
#IBAction func submit(_ sender: Any)
{
let name = String(nameTextField.text!)
let height = Double(heightTextField.text!)!
let weight = Double(weightTextField.text!)!
let age = Double(ageTextField.text!)!
let sex = String(sexTextField.text!)
let new = Profile.init(name, height, weight, age, sex)
main?.profileSubmit(new)
new.display()
dismiss(animated: true, completion: nil)
}
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
I guess that on coming back from newProfile viewDidLoad is called -> you reset the picker in viewDidLoad by setting it to a new instance. Try to remove the new initialization in viewDidLoad :
super.viewDidLoad()
pickerView = UIPickerView()
The picker is already initialized here:
var pickerView = UIPickerView()
Also, I think the picker components start with 0 - so if there is only 1 component it should be:
pickerView.reloadComponent(0)

Using same pickerView for two buttons returning empty data

Here's my code . I am trying to use UIPickerview for few buttons with different data. but it show's me blank gray picker view when I run my project. some told me that I have to reload the pickerView but I used it for example "mainPV.delegate = self ..... Please I need help guys if someone can help me
import UIKit
class SearchBuyVC: UIViewController {
#IBOutlet weak var optionV: UIView!
#IBOutlet weak var doneBtn: UIButton!
#IBOutlet weak var searchBtn: UIButton!
// picker view
#IBOutlet var mainPV: UIPickerView! // main
#IBOutlet var secPV: UIPickerView! //type
#IBOutlet var minPV: UIPickerView! //priceMin
#IBOutlet weak var typeBtn: UIButton!
#IBOutlet weak var PriceMinBtn: UIButton!
var optionSelector = 0
let searchData = ["Search by Areas", "Search by Map", "Search by LRT/MRTs", "Search by Schools", "Search by Propery Name"]
let typeData = ["All Residental", "All Commerical"]
let minNum = ["Any", "100 k", "200 k", "300 k", "400 k", "500 k", "600k ", "700 k"]
override func viewDidLoad() {
super.viewDidLoad()
setUpNav(arrowType: 2)
mainPV = UIPickerView()
secPV = UIPickerView()
minPV = UIPickerView()
mainPV.delegate = self
secPV.delegate = self
minPV.delegate = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
//Dispose of any resources that
}
override func viewDidAppear(_ animated: Bool) {
self.navigationController?.setNavigationBarHidden(false, animated: true)
}
#IBAction func selectOptionsPressed(_ sender: Any) {
openOptions()
mainPV.delegate = self
secPV.delegate = self
minPV.delegate = self
}
#IBAction func typeSelect(_ sender: Any) {
openOptions()
mainPV.delegate = self
secPV.delegate = self
minPV.delegate = self
}
#IBAction func minPriceBtn(_ sender: Any) {
openOptions()
mainPV.delegate = self
secPV.delegate = self
minPV.delegate = self
}
#IBAction func donePressed(_ sender: Any) {
switch optionSelector {
case 0:
FiltersController.instance.showAreaFilter(nc: self.navigationController!)
case 1:
FiltersController.instance.showMapFilter(nc: self.navigationController!)
case 2:
FiltersController.instance.showTrainStations(nc: self.navigationController!)
case 3:
FiltersController.instance.showSchoolFilter(nc: self.navigationController!)
default:
FiltersController.instance.showNameFilter(nc: self.navigationController!)
}
closeOptions()
}
func openOptions() {
optionV.isHidden = false
mainPV.isHidden = false
minPV.isHidden = false
doneBtn.isHidden = false
secPV.isHidden = false
}
func closeOptions(){
optionV.isHidden = true
mainPV.isHidden = true
minPV.isHidden = true
doneBtn.isHidden = true
secPV.isHidden = true
}
#IBAction func nextPressed(_ sender: Any) {
ListingController.instance.showBuyListing(nc: self.navigationController!)
}
}
extension SearchBuyVC: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == mainPV {
return searchData.count
}
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == mainPV{
return searchData[row]
}
if pickerView == secPV{
return typeData[row]
}
if pickerView == minPV{
return minNum[row]
}
return ""
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
optionSelector = row
if pickerView == mainPV{
searchBtn.setTitle(searchData[row], for: .normal)
}
if pickerView == secPV{
typeBtn.setTitle(typeData[row], for: .normal)
}
if pickerView == minPV{
PriceMinBtn.setTitle(minNum[row], for: .normal)
}
}
}
Also need to set dataSource for the pickerViews. So that the methods of UIPickerViewDataSource called which are responsible for returning all the data to UIPickerView. Your class must to confirm the UIPickerViewDataSource protocol.
Ex:
picker_country.dataSource = self
At first import the UIPickerView protocols within the class as,
class SearchBuyVC: UIViewController UIPickerViewDelegate, UIPickerViewDataSource
and add the following lines also to call the datasource functions,
mainPV.delegate = self
secPV.delegate = self
minPV.delegate = self
mainPV.dataSource = self
secPV.dataSource = self
minPV.dataSource = self

swift - Add blur to UIView in order to "blur" the Controller below? Read before

I know that this question could appears a duplicate, but please read before downvote!
I have this ReachabilityViewController with a UIView named pickerView in it, as you can see in this picture below
My desired result is this:
but I get this instead:
This is my class of the viewController:
import UIKit
class ReachabilityViewController: UIViewController {
//MARK: pickerView outlets and actions
#IBOutlet weak var pickerView: UIView!
#IBOutlet weak var saveButton: UIButton!
#IBOutlet weak var cancelButton: UIButton!
#IBOutlet weak var startEndLabel: UILabel!
#IBOutlet weak var timePicker: UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
pickerView.frame = CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
}
// MARK: - Table view data source
extension ReachabilityViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.view.addSubview(pickerView)
pickerView.alpha = 0.0
UIView.animate(withDuration: 0.3) {
self.pickerView.alpha = 1.0
}
}
}
how to get the effect I want?
I already set pickerView backgroundColor as clear.
this is what I've done
class ViewController: UIViewController,UIPickerViewDataSource, UIPickerViewDelegate {
var pickerDataSource = ["White", "Red", "Green", "Blue"];
#IBOutlet var pickerView: UIPickerView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.regular)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = view.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.pickerView.delegate = self
self.pickerView.dataSource = self
self.view.addSubview(blurEffectView)
self.view.bringSubview(toFront: self.pickerView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerDataSource.count;
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return pickerDataSource[row]
}
}

Pass data back in navigation controller Swift 3

I am rather new to Xcode and Swift and I am trying to pass data back from a previous page. So far what I have works but it leverages the segue I created to show the previous page. This would not be a problem except it is in a navigation view controller. So when you click the save button it passes the data to my choices view controller but if you click the back button on the page it goes back to the editing page. I want it to instead travel back in the navigation pane so that way when you click the back page it instead takes it to the page that says view my chart. So I don't think using a segue to do this is the right option because I am typically passing the data forward. I want to pass the data back to the previous navigation view controller. You will see my cancel button does this.
Story Board
Edit ViewController
class EditUserViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
var officeSelected = ""
var utilSelected = ""
#IBOutlet weak var officePicker: UIPickerView!
#IBOutlet weak var slider: UISlider!
#IBAction func UtilSlider(_ sender: UISlider) {
slider.value = roundf(slider.value)
utilSelected = String(Int(sender.value))
}
let offices = ["NYC", "LA", "Boston"]
func numberOfComponents(in pickerView: UIPickerView) -> Int
{
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
{
return offices.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
{
return offices[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
officeSelected = offices[row]
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func CancelEdit(_ sender: UIBarButtonItem) {
self.dismiss(animated: true, completion: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let choicesView = segue.destination as! ChoicesViewController
choicesView.officeText = officeSelected
choicesView.utilText = utilSelected
}
}
choices ViewController
class ChoicesViewController: UIViewController{
#IBOutlet weak var officeLabel: UILabel!
#IBOutlet weak var AvalLabel: UILabel!
var utilText = String()
var officeText = String()
override func viewDidLoad() {
super.viewDidLoad()
officeLabel.text = officeText
AvalLabel.text = utilText
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Error about Picker View

I try to show "man" and "woman" but getting "signal sigabrt". Anyone please help me solve my problem
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate {
#IBOutlet weak var pkvTest: UIPickerView!
var a : [String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
a = ["man", "woman"]
}
func numberOfComponentsInPickerView(pickerView : UIPickerView) -> Int {
return 1
}
func pickerView(pickerView : UIPickerView, numberOfRowsInComponent component : Int) -> Int {
return a.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return a[row]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Your first two picker view functions have the wrong names. The reason for this is that you forgot to declare your view controller as adopting UIPickerViewDataSource. As soon as you do that, the compiler will wake up to the problem and alert you to it.
Try this. Looks like you're missing the delegate and datasource in the viewdidload
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDatasource {
#IBOutlet weak var pkvTest: UIPickerView!
var a : [String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.pkvTest.delegate = self
self.pkvTest.datasource = self
a = ["man", "woman"]
}

Resources