CODE HAS BEEN UPDATED AND IS WORKING AS EXPECTED
I have a View Controller with a text field and a PickerView. I want to display the data i have stored in Firebase inside the PickerView. I'm able to retrieve and print the data from Firebase but I can't find a way to display it inside the PickerView. Here is my code:
import UIKit
import Firebase
class pickerVC: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
#IBOutlet weak var labelTxt: UITextField!
#IBOutlet weak var infoPickerViewer: UIPickerView!
var dbRef: CollectionReference!
var pickerView: UIPickerView?
var itemsClass = [ItemInfo]()
override func viewDidLoad() {
super.viewDidLoad()
let pickerView = UIPickerView()
infoPickerViewer.delegate = self
infoPickerViewer.dataSource = self
dbRef = Firestore.firestore().collection(ITEMS_REF)
labelTxt.inputView = pickerView
labelTxt.delegate = self
self.infoPickerViewer = pickerView
self.infoPickerViewer?.delegate = self
self.infoPickerViewer?.dataSource = self
self.infoPickerViewer.reloadAllComponents()
getItems()
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func textFieldDidBeginEditing(_ textField: UITextField) {
labelTxt = textField
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.pickerView?.reloadAllComponents()
return true
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if labelTxt.isFirstResponder {
return self.itemsClass.count
}
return 0
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if labelTxt.isFirstResponder {
return itemsClass[row].itemName
}
return nil
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if labelTxt.isFirstResponder {
let item = itemsClass[row].itemName
labelTxt.text = item
}
}
func getItems() {
dbRef.getDocuments { (snapshot, error) in
if let err = error {
debugPrint("error fetching docs: \(err)")
} else {
self.infoPickerViewer.reloadAllComponents()
let snap = snapshot
for document in snap!.documents {
let data = document.data()
let itemCode = data[ITEMS_CODE] as? String ?? ""
let itemName = data[ITEMS_NAME] as? String ?? ""
let t = ItemInfo(itemCode: itemCode, itemName: itemName)
self.itemsClass.append(t)
print("ITEMS_CODE", itemCode as Any)
print("ITEMS_NAME", itemName as Any)
}
}
}
}
}
The Firebase DB is structured as follow:
collection/AutoID/itemCode: "item1"
itemName: "item2"
collection/AutoID/itemCode: "item3"
itemName: "item4"
I only need to display the itemName inside the PickerView, the itemCode I'm going to use it to run a query depending on the selection in the PickerView.
Any help with this is greatly appreciated.
Related
how can I push the User Selection of a UIPicker to Firebase Database? So for example he hit on "male" than it will be stored in the Firebase Database...
My code for the UI Picker
class AddExtraData: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return data.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return data[row]
}
#IBOutlet var pickerView: UIPickerView!
let data = ["male", "female", "else"]
override func viewDidLoad() {
super.viewDidLoad()
pickerView.dataSource = self
pickerView.delegate = self
}
EDIT:
Database
Here is my database.
Now I want to get to write the data which is stored in seclectedYearPicker to the database.
var ref: DatabaseReference!
ref = Database.database().reference()
let selectedYearPicker = data[pickerView.selectedRow(inComponent: 0)]
print(selectedYearPicker)
let userID = Auth.auth().currentUser!.uid
ref.child("users").child(userID).setValue(["gender": selectedYearPicker])
}
If I make this, there will be a new dataset:
let db = Firestore.firestore()
db.collection("users").whereField("uid", isEqualTo: Auth.auth().currentUser?.uid ?? "x")
.getDocuments { (querySnapshot, err) in
if err != nil {
print("Failed")
return
}
let userdocid = querySnapshot!.documents[0].documentID
db.collection("users").document(userdocid).setData(["koordinaten" : selectedYearPicker])
}
I want to choose and display the correct dataset from Firebase, based on the pickerView selection.
The main problem - the values of the UILabels are not changing.
The second thing I would like to note, that the pickerView does not disappear after I click on one of the values in it.
import UIKit
import Firebase
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet weak var priceView: UILabel!
#IBOutlet weak var dayView: UILabel!
#IBOutlet weak var monthView: UILabel!
#IBOutlet weak var personPicker: UITextField!
var ref: DatabaseReference?
var databaseHandle: DatabaseHandle?
var postData = [String]()
var person : String = "jack"
let people = ["jack", "jenny", "don"]
override func viewDidLoad() {
super.viewDidLoad()
let pickerView = UIPickerView()
personPicker.delegate = self
personPicker.inputView = pickerView
ref = Database.database().reference()
ref?.child("xf").child(person).child("price").observe(.value, with: { (snapshot) in
if let i = snapshot.value as? Double
self.priceView.text = "\(i)"
self.priceView.reloadInputViews()
}
})
ref?.child("xf").child(person).child("day").observe(.value, with: { (snapshot) in
if let i = snapshot.value as? String {
self.dayView.text = "\(i)"
self.dayView.reloadInputViews()
}
})
ref?.child("xf").child(person).child("month").observe(.value, with: { (snapshot) in
if let i = snapshot.value as? String {
self.monthView.text = "\(i)"
self.monthView.reloadInputViews()
}
})
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return people.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return people[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
personPicker.text = people[row]
person = people[row]
}
}
For the first issue, I tried adding the 'person = people[row]' but the values in the UILabes do not change
For the issue with the pickerView removal, I tried adding 'pickerView.isHidden = true', but it only removes the values, not the card
Xcode Version 12.3
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
}
From "var myValue:[Double]..." and "var activeCurrency:Double = 0;" to the third pickerview code, I am not sure what to do in order to fix the "self.myValues.append((Url as? Double)!)" so that my app displays the currency amount. I have searched everywhere, and have no luck in finding anything. You are my last hope, please help. I'm still fairly new to coding, so I may not know the certain jargon.
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
var myCurrency:[String] = []
var myValues:[Double] = []
var activeCurrency:Double = 0;
//OBJECTS
#IBOutlet weak var textbox: UITextField!
#IBOutlet weak var pickerView: UIPickerView!
#IBOutlet weak var output: UILabel!
//CREATING PICKER VIEW
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return myCurrency.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return myCurrency[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
activeCurrency = myValues[row]
}
//BUTTON
#IBAction func action(_ sender: AnyObject) {
if (textbox.text != "") {
output.text = String(Double(textbox.text!)! * activeCurrency)
}
}
override func viewDidLoad() {
super.viewDidLoad()
//DATA GRABBING
let url = URL(string: "https://min-api.cryptocompare.com/data/all/coinlist")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
print ("ERROR")
}
else {
if let content = data {
do {
let myJson = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
if let rates = myJson["Data"] as? NSDictionary {
for (Name, Url) in rates {
self.myCurrency.append((Name as? String)!)
self.myValues.append((Url as? Double)!)
}
}
}
catch {
}
}
}
if data != nil {
DispatchQueue.main.async { // Correct
self.pickerView.reloadAllComponents()
}
}
}
task.resume()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I have a problem in returning the value from a picker and comparing it to the value of an attribute. Basically, i have a Floor entity which has a attribute "floorNumber". From the picker I need to get the floor number and match it to the correct entity object so I can start assigning rooms to individual floors. I have implemented the delegate and the data source for the picker and looked at other questions on this site but I'm getting a bit confused.
Please have look at my implementation and please tell me what am I doing wrong. I have an optional "pickedFloor" which is nil even though it is being set and if I try to unwrap it it will crash it. Thank you for your help
class SetNumberOfRoomsPerFloor: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
//MARK: - Properties
#IBOutlet private weak var floorPicker: UIPickerView!
#IBOutlet private weak var numberOfRoomsPerFloor: UITextField!
private var managedObjectContext: NSManagedObjectContext!
internal var floorValue: Int16?
private var convertedFloorValues = [String]()
private var storedFloors = [Floors]()
private var pickedFloor: Int16?
private var roomNumberValue: Int16 {
get {
return Int16(numberOfRoomsPerFloor.text!)!
}
}
override func viewDidLoad() {
super.viewDidLoad()
managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
floorPicker.delegate = self
floorPicker.dataSource = self
loadFloorData()
spinnerItems()
}
#IBAction func setTheFloors(_ sender: UIButton) {
if storedFloors.count > 0 {
if storedFloors.first?.floorNumber == pickedFloor {
storedFloors.first?.numberOfRooms = roomNumberValue
print("\(storedFloors.first?.floorNumber) + \(storedFloors.first?.numberOfRooms)")
}
}
}
#IBAction func nextStep(_ sender: UIButton) {}
private func loadFloorData() {
let floorRequest: NSFetchRequest<Floors> = Floors.fetchRequest()
do {
storedFloors = try managedObjectContext.fetch(floorRequest)
} catch {
print("could not load data from core \(error.localizedDescription)")
}
}
private func spinnerItems() {
for i in 0...floorValue! - 1 {
convertedFloorValues.append(String(i))
}
}
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return convertedFloorValues.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return convertedFloorValues[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let selection = Int16(convertedFloorValues[row]) // not sure I have to do this part.
pickedFloor = selection
}
}
Inside this function, you should do this
private func spinnerItems() {
for i in 0...floorValue! - 1 {
convertedFloorValues.append(String(i))
}
if convertedFloorValues.count >= 1 {
pickedFloor = Int16(convertedFloorValues[0])
}
}
Like I said in the comments, didSelectRow never gets called if you don't actually move the picker view.
If the user hasn't selected anything in pickerview then pickedFloor will be nil.Try this.
#IBAction func setTheFloors(_ sender: UIButton) {
if storedFloors.count > 0 {
if storedFloors.first?.floorNumber == convertedFloorValues[floorPicker.selectedRow(inComponent: 0)] {
storedFloors.first?.numberOfRooms = roomNumberValue
print("\(storedFloors.first?.floorNumber) + \(storedFloors.first?.numberOfRooms)")
}
}
}