beginner with Swift with an error UIPicker - swift

I am building a simple app that has a PickerView with 3 selections that should link to 3 viewControllers each named FirstViewController, SecondViewController and ThirdViewController.
But I am getting this error
> NSInvalidArgumentException', reason: 'Receiver (<Scroller.ViewController: 0x7ff7b5e0b670>) has no segue with identifier 'SecondSegue'
I have three options in the picker and a button to go to that selection's viewController:
My code below works on first loading then crashes
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBAction func continueButtonPressed(_ sender: AnyObject) {
self.performSegue(withIdentifier: "\(chosenState)Segue", sender: nil)
print("no chance")
}
#IBOutlet weak var pickerView: UIPickerView!
var pickerData = ["First","Second","Third"]
var chosenState = ""
override func viewDidLoad() {
super.viewDidLoad()
print("Help")
pickerView.delegate = self
pickerView.dataSource = self
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// The number of columns of data
// The number of rows of data
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
}
// 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? {
return pickerData[row]
}
//Called when the user changes the selection...
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
chosenState = pickerData[row]
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
}
can anyone help me understand how to fix this ?
Have I named the Segues ok? They are all named the same - is that correct?

You have to set the segue identifier to second view controller as SecondSegue

It seems your SecondSegue to your second UIViewController has not been named properly.
Be careful, it is case sensitive, it must be named precisely SecondSegue. And after having changed the name, don't forget to validate your input with the return key.

Related

Refreshing UIPicker from user input

I am new to Xcode/Swift and working on an assignment for which I need some help. I have a simple program that displays a list of names when started. I want to take a new name, from the UITextField, and add it to the data for the picker after the item that is currently selected. The new added name should be shown in the picker as the selected item (so the previously selected item would be immediately above it on the picker’s display at that point). I have the program working thus far, however, my "picker.reloadAllComponents()" function seems to be breaking something. When I leave this in place, none of the data in the picker is being shown. When I remove it, I don't know if my insertButton action is working. Where can I refresh the picker data such that the picker data is being seen in my simulator? Thanks.
import UIKit
class ViewController: UIViewController,
UIPickerViewDelegate, UIPickerViewDataSource {
var characterNames = [
"Luke", "Leia", "Han", "Chewbacca", "Artoo",
"Threepio", "Lando"]
#IBOutlet weak var userInput: UITextField!
#IBOutlet weak var picker: UIPickerView!
#IBAction func selectButton(_ sender: UIButton) {
let row = picker.selectedRow(inComponent: 0)
let selected = characterNames[row]
let title = "You selected \(selected)!"
let alert = UIAlertController(
title: title,
message: "Thank you for choosing",
preferredStyle: .alert)
let action = UIAlertAction(
title: "You're welcome",
style: .default,
handler: nil)
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
#IBAction func insertButton(_ sender: UIButton) {
characterNames.insert(userInput.text!, at: picker.selectedRow(inComponent: 0))
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK:-
// MARK: Picker Data Source Methods
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView,
numberOfRowsInComponent component: Int) -> Int {
return characterNames.count
}
// MARK: Picker Delegate Methods
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
picker.reloadAllComponents()
return characterNames[row]
}
}
Don't call picker.reloadAllComponents() from within the titleRorRow method as I think this may be invoking an infinite loop - this delegate method should return the title for that row only, as your second line is doing correctly. So remove it from there.
Instead, place it in your insertButton method after you have updated the source. This will cause the data to be reloaded, and the data source methods called again to repopulate the picker.
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return characterNames[row]
}
#IBAction func insertButton(_ sender: UIButton) {
characterNames.insert(userInput.text!, at: picker.selectedRow(inComponent: 0))
picker.reloadAllComponents()
}

Swift UIPickerView defaults to last option regardless of selected option

I have a UIPickerView that when tapping the done button, keeps selecting the last option of the Array. I can tap on either the UITextField or a button I'm using that assigns the UITextField as the first responder. My code is as follows:
Edit. I should also mention that I'm using Xcode 11 GM Seed if that was to make a difference. I tested a clean version of the code shown below on a separate project with nothing else and it is displaying the same behavior.
#IBOutlet weak var sortTypeTextField: UITextField!
var selectedSortOption = String()
let sortOptions = [
USER_REVIEWS_SORT_OPTION_DATE,
USER_REVIEWS_SORT_OPTION_LIKES,
USER_REVIEWS_SORT_OPTION_DISLIKES
]
sortOptions above is an array of Strings located in a different file but for the purpose of this question I’ll add here:
let USER_REVIEWS_SORT_OPTION_DATE = "Date"
let USER_REVIEWS_SORT_OPTION_LIKES = "Number of Likes"
let USER_REVIEWS_SORT_OPTION_DISLIKES = "Number of Dislikes"
let DONE_TOOLBAR_BUTTON_TITLE = "Done"
I have a function setupUI which I call in viewDidLoad along with the value for the sortTypeTextField. The value is the first String in the array when the viewController first loads.
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
func setupUI() {
sortTypeTextField.text = sortOptions[0]
createSortPicker()
createPickerToolbar()
}
func createSortPicker() {
let sortPicker = UIPickerView()
sortPicker.delegate = self
sortTypeTextField.inputView = sortPicker
}
func createPickerToolbar() {
let toolBar = UIToolbar()
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: DONE_TOOLBAR_BUTTON_TITLE, style: .plain, target: self, action: #selector(dismissKeyboard))
toolBar.setItems([doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
sortTypeTextField.inputAccessoryView = toolBar
}
#objc override func dismissKeyboard() {
view.endEditing(true)
}
I’m also using a button to display the UIPicker as shown here:
#IBAction func sortRatingsButtonWasTapped(_ sender: Any) {
sortTypeTextField?.becomeFirstResponder()
}
As shown below, I want for the sortTypeTextField value to change to the selected option but for some reason when tapping the Done button in the toolbar, the text shown is always the third String in the array regardless if I have chosen the first, the second or the third.
extension ReviewsViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
sortOptions.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return sortOptions[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedSortOption = sortOptions[row]
sortTypeTextField.text = selectedSortOption
}
}
It seems to be a bug in the simulator. I tested the my code above and the code provided by Abdul Karim Khan on my device and the work as they should. The label updates according to the option selected in the picker view.
This is how I created pickerView,
class ViewController: UIViewController {
#IBOutlet weak var selectaday: UITextField!
let days = ["monday","wednesday"]
var selectedDay: String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
createDayPicker()
}
func createDayPicker(){
let dayPicker = UIPickerView()
dayPicker.delegate = self
selectaday.inputView = dayPicker
}
}
extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource{
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return days.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return days[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedDay = days[row]
selectaday.text = selectedDay
}
}

Using picker view with UIButton to open a new TableView

I have a picker view and tableviews for each picker row programmed and I'd like to connect them via a UIButton. Any suggestions for a swift function to connect the Pickerview row with the botton to open that picker's table? (code below)
Thanks!
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var Picker1: UIPickerView!
var Array = ["G: Classroom friendly", "PG-13: Swear words OK(no sexual innuendo)", "R: Anything goes!"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
Picker1.delegate = self
Picker1.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return Array[row]
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return Array.count
}
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
#IBAction func Submit(_ sender: Any) {
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
}
#IBAction func ContinueBotton(_ sender: UIButton) {
}
}
class ViewController1: UITableViewController {
#IBOutlet var ViewController1: UITableView!
var GRating = [GN]()

making a drop-down list in Swift 3

I'm trying to make drop-down list where picker view is not visible until user clicks on textfield. Then picker view disappears after user makes selection from pickerView. Currently, the picker View does not show up at all when I click on textfield.
import UIKit
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet weak var textBox: UITextField!
#IBOutlet weak var pickerView: UIPickerView!
var choices = ["SortBy:", "Date(ascending)", "Date(descending)","Calories Burned(descending)","Duration(descending)"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
self.view.endEditing(true)
return choices[row]
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return choices.count
}
fun pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.textBox.text = self.choices[row]
self.pickerView.isHidden = true
print("hello")
}
func textFieldDidBeginEditing(TextField: UITextField){
if TextField == self.textBox {
self.pickerView.isHidden = false
TextField.endEditing(true)
}
}
override func viewDidLoad() {
self.pickerView.isHidden = true
super.viewDidLoad()
}
}
try this :
override func viewDidLoad() {
self.pickerView.isHidden = true
super.viewDidLoad()
self.textBox.delegate = self
self.pickerView.delegate = self
}

Swift Picker Items

I'm trying to make items show up on my pickerView, I can't seem to figure out why its not showing up. Any Suggestions?
import UIKit
class InspectionViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var picker: UIPickerView!
var pickerData: [String] = [String]();
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Connect data:
self.picker.delegate = self;
self.picker.dataSource = self;
// Input data into the Array:
pickerData = ["53W4", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6"];
}
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 pickerData.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return pickerData[row]
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
You should use this:
func pickerView(
_ pickerView: UIPickerView,
titleForRow row: Int,
forComponent component: Int
) -> String? {
pickerData[row]
}
instead of:
func pickerView(
pickerView: UIPickerView,
titleForRow row: Int,
forComponent component: Int
) -> String! {
pickerData[row]
}
The diff is in Omitting Argument Labels.
Here is a doc link