Accessing a variable stored within a class Swift - class

I can't figure out why I can't access this variable, see below, I want the value of sport result when it's clicked, however sportResult.selectedSport returns nil?
let sportPickerData = SportPickerData()
override func viewDidLoad() {
super.viewDidLoad()
sportPickerView.delegate = sportPickerData
sportPickerView.dataSource = sportPickerData
class SportPickerData: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
var sports = ["Football", "Baseball", "Hockey", "Basketball"]
var selectedSport: String?
func numberOfComponentsInPickerView(yearPicker: UIPickerView) -> Int {
return 1
}
func pickerView(yearPicker: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return sports.count
}
func pickerView(yearPicker: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedSport = sports[row]
}
func pickerView(yearPicker: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return "\(sports[row])"
}
}
let sportResult = SportPickerData()
#IBAction func button(sender: UIButton) {
label.text = sportResult.selectedSport
}

sportResult its not a delegate or a data source of your picker view so its selectedSport property will never be initialized since its didSelectRow method will be never called. To get the selectedSport you have to get it from sportPickerData which is actually the delegate and data source of your picker
let sportResult = SportPickerData() // delete this line
#IBAction func button(sender: UIButton) {
label.text = sportPickerData.selectedSport
}

Related

REALM Append list into linkingObjects

I want to use realm to append all data in one VC.
parentVC is showing Category List, in ParentVC can only append new Category
childVC is showing toDoItem List, and can only append to selectedCategory.toDoList
I created a new VC "addToDoListVC", to achieve result of "Adding new toDoItems to selected todoListCategory".
below is my code and image shown is the new addToDoListVC layout.
addToDoItemVC layout
class Category : Object {
#objc dynamic var categoryName : String = ""
let ofToDoItem = List<ToDoItem>()
}
class ToDoList : Object {
#objc dynamic var toDoItem : String = ""
var parentCategory = LinkingObjects(fromType: Category.self, property: "ofToDoItem")
}
addItemVC
let realm = try! Realm()
var categorySelection : Results<Category>?
#IBOutlet weak var categoryName: UILabel!
#IBOutlet weak var categoryNamePicker: UIPickerView!
#IBAction func addItemBtnPressed(_ sender: UIButton) {
if let currentCategory = self.categorySelection {
do {
try! realm.write
let newToDoItem = ToDoList()
**// HOW DO I ADD THE ITEM TO SELECTED CATEGORY?**
newToDoItem.toDoItem = textField.text
selectedCategory[**???**].ofToDoItem.append(newToDoItem)
**[// I can append data into selected category by "selectedCategory\[0\].ofToDoItem.append(newToDoItem)" but it is hardcoded.][1]**
}
}
}
//MARK:- PICKERVIEW METHODS
extension ParentVC : UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return categorySelection?.count ?? 0
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return categorySelection?[row].categoryName
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
categoryName.text = categorySelection?[row].categoryName
}

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
}
}

How to use multiple UIPickerViews in one view controller

I am trying to set up 2 UIPickerViews in 1 view controller. I have not been able to find resources that solve my problem.
I have tried following the answer from Diavel Rider on How to use 2 UIPickerView's in one View Controller?. I got some errors from that. I have also tried adding tags but was not able to successfully do that. I am using Swift 4.
Here is the code of my view controller:
import UIKit
class FirstViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ foodTypeUIPickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
var countrows : Int = nutritionPickerData.count
if pickerView == foodTypeUIPickerView { **[Error Here: "Binary operator '==' cannot be applied to operands of type '_' and 'UIPickerView'"]**
countrows = self.foodTypePickerData.count
}
return countrows
}
func pickerView(_ foodTypeUIPickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == nutritionUIPickerView { **[Error Here: "Binary operator '==' cannot be applied to operands of type '_' and 'UIPickerView'"]**
let titleRow = nutritionPickerData[row]
return titleRow
} else if pickerView == foodTypeUIPickerView { **[Error Here: "Binary operator '==' cannot be applied to operands of type '_' and 'UIPickerView'"]**
let titleRow = foodTypePickerData[row]
return titleRow
}
return ""
}
#IBOutlet weak var nutritionUIPickerView: UIPickerView!
#IBOutlet weak var foodTypeUIPickerView: UIPickerView!
var nutritionPickerData = ["Protein", "Fiber", "Iron", "Fat", "Sodium", "Calcium/Vitamin D", "Energy", "Carbohydrates", "Cholestorol"]
var foodTypePickerData = ["Fruits", "Vegetables", "Legumes and Beans", "Grain", "Meat", "Dairy"]
#IBAction func submitUIButton(_ sender: Any) {
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.nutritionUIPickerView.delegate = self
self.nutritionUIPickerView.dataSource = self
self.foodTypeUIPickerView.delegate = self
self.foodTypeUIPickerView.dataSource = self
}
}
I need to use 2 picker views in 1 view controller. How do I do this?
You are referencing a non-existent variable named pickerView. You should update the parameter name to pickerView to avoid issues.
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == foodTypeUIPickerView {
return self.foodTypePickerData.count
} else {
return self. nutritionPickerData.count
}
}
Make a similar change to the other delegate/data source methods.
You should separate your data sources and delegates and not put them inside your view controller. Set those as the delegate and datasource. Code written in swift 4.2 xcode 10.1
class ViewController: UIViewController {
#IBOutlet weak var foodPicker: UIPickerView!
#IBOutlet weak var nutritionPicker: UIPickerView!
var foodData = FoodData()
var nutritionData = NutritionData()
override func viewDidLoad() {
super.viewDidLoad()
foodPicker.delegate = foodData
foodPicker.dataSource = foodData
nutritionPicker.delegate = nutritionData
nutritionPicker.dataSource = nutritionData
}
#IBAction func actionButton(_ sender: UIButton) {
let food = foodPicker.delegate?.pickerView!(foodPicker, titleForRow: foodPicker.selectedRow(inComponent: 0), forComponent: 0)
let nutrition = nutritionPicker.delegate?.pickerView!(nutritionPicker, titleForRow: nutritionPicker.selectedRow(inComponent: 0), forComponent: 0)
print("You picked: \(food) and \(nutrition)")
}
}
class FoodData: NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
var foodTypePickerData = ["Fruits", "Vegetables", "Legumes and Beans", "Grain", "Meat", "Dairy"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return foodTypePickerData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return foodTypePickerData[row]
}
}
class NutritionData: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
var nutritionPickerData = ["Protein", "Fiber", "Iron", "Fat", "Sodium", "Calcium/Vitamin D", "Energy", "Carbohydrates", "Cholestorol"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return nutritionPickerData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return nutritionPickerData[row]
}
}

How to connect UIPickerView + Button + call dictionary to display in label

I have a label, a picker (years), and a button. I want to be able to select the year on the picker, hit the button, and then display data associated with the year (a dictionary). Here's my code so far
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var picker: UIPickerView!
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent
component: Int) -> Int {
return years.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int,
forComponent component: Int) -> String! {
return years[row]
}
/* func pickerView(pickerView: UIPickerView!, didSelectRow row: Int,
inComponent component: Int) {
label.text = "\(years[row])"
}
*/
#IBAction func button(sender: UIButton) {
label.text =
}
here is my Model:
let years = ["2015", "2014", "2013", "2012"]
let winners = [
2015: "Patriots",
2014: "Seahawks",
2013: "Ravens",
2012: "Giants"
]
You need to do a few things to make this work. First, make your viewController conform to the UIPickerViewDataSource and UIPickerViewDelegate and set your picker's data source and delegate in viewDidLoad. Then you'll want to use the delegate method pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) to respond to changes to the pickerView. Store the selection in an instance variable and you should be good to go:
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var picker: UIPickerView!
let years = [2015, 2014, 2013, 2012]
let winners = [
2015: "Patriots",
2014: "Seahawks",
2013: "Ravens",
2012: "Giants"
]
var selectedYear: Int?
override func viewDidLoad() {
super.viewDidLoad()
picker.delegate = self
picker.dataSource = self
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return years.count
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedYear = years[row]
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return "\(years[row])"
}
#IBAction func button(sender: UIButton) {
if let year = selectedYear {
if let winner = winners[year] {
label.text = winner
}
}
}
}

pickerView shows up as question marks instead of data?

I am trying to add a pickerview to my iphone application but instead of showing string from my array it shows question marks. Does anyone know why? I've been trying to figure it out for the past hour... Here is my code of the controller that contains the pickerview:
class NewIssueViewController: UIViewController, UIPickerViewDelegate {
var componentArr = ["component1","component2","component3","component4"]
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 CancelPressed(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func AddPressed(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
func numberOfComponentsInPickerView(pickerView: UIPickerView!) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView!, numberOfRowsInComponent component: Int) -> Int {
return componentArr.count
}
func pickerView(pickerView: UIPickerView!, titleForRow row: Int, forComponent component: Int) -> String! {
return componentArr[row]
}
}
You set your picker view's datasource, but didn't set its delegate.
As a result pickerView:titleForRow: never gets called.
You should either connect the PickerView's Datasource and Delegate in the storyboard or set them programatically. See the image below.
New Swift 3 has deprecated usage of above methods,
i have implemented the following to make them work. (Some underscore added in param.
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]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
/*if(row == 0)
{
self.view.backgroundColor = UIColor.whiteColor();
}
else if(row == 1)
{
self.view.backgroundColor = UIColor.redColor();
}
else if(row == 2)
{
self.view.backgroundColor = UIColor.greenColor();
}
else
{
self.view.backgroundColor = UIColor.blueColor();
}*/
}
Just add self.pickerOutletReference.delegate = self on viewDidLoad() menthod