two table view in one view controller, swift - swift

My view controller has two table views. The askTable works, but bidTable doesn't work. No error comes out.
Here is what it prints. The array exactly contains the elements I want. Not sure what I did wrong or miss for bidTable. Also, wondering why "Hi" is never printed too.
askPriceArray: []
bidPriceArray: []
bid: 0
Above repeat several times
askPriceArray: []
bidPriceArray: ["21"]
ask: 0
askPriceArray: []
bidPriceArray: ["21", "212"]
ask: 0
askPriceArray: ["21"]
bidPriceArray: ["21", "212"]
ask: 1
import UIKit
class ProductDetailViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
{
#IBOutlet weak var bidTable: UITableView!
#IBOutlet weak var askTable: UITableView!
var askPriceArray = [String]()
var bidPriceArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.bidTable.dataSource = self
self.bidTable.delegate = self
self.askTable.dataSource = self
self.askTable.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(animated: Bool) {
.....insert elements to arrays from Parse..........
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("askPriceArray: \(self.askPriceArray)")
print("bidPriceArray: \(self.bidPriceArray)")
if tableView == self.askTable {
print("ask: \(askPriceArray.count)")
return askPriceArray.count
} else {
print("bid: \(bidPriceArray.count)")
return bidPriceArray.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == self.askTable{
let cell:DetailAskTableViewCell = tableView.dequeueReusableCellWithIdentifier("askCell") as! DetailAskTableViewCell
cell.askPriceAndQuantity.text = self.askPriceArray[indexPath.row]
return cell
} else {
print("Hi")
let cell:DetailBidTableViewCell = tableView.dequeueReusableCellWithIdentifier("bidCell") as! DetailBidTableViewCell
cell.bidPriceAndQuantity.text = self.bidPriceArray[indexPath.row]
return cell
}
}
}

Be sure that you are reloading both UITableViews after you have retrieved your data from Parse.

Related

Label Data lost when scrolling in UITableView

I made a table view with a label that increments and decrements on pressing a button and another button to show the text in another label outside the UItableView. Everything works fine but when I scroll the Tableview the value resets to zero!
Before Scrolling
After Scrolling
My ViewController class
class ViewController: UIViewController{
var numArray = [Value]()
var initialValue = 0
#IBOutlet weak var tableView : UITableView!
#IBOutlet weak var lblOutput : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
for _ in 0 ... 100{
numArray.append(Value(number: initialValue))
}
self.lblOutput.text = "\(initialValue)"
tableView.delegate = self
tableView.dataSource = self
tableView.reloadData()
}
}
extension ViewController : UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",for: indexPath) as? ControllerTableViewCell else{fatalError("Error in creating cells")}
cell.delegate = self
cell.data = numArray[indexPath.row]
cell.lblInput.text = "\(cell.data.number)"
return cell
}
}
extension ViewController : MyTableViewCellDelegate{
func DidPrint(Data: String) {
self.lblOutput.text = "\(Data)"
}
}
My TableViewCell class
protocol MyTableViewCellDelegate : AnyObject {
func DidPrint(Data: String)
}
class ControllerTableViewCell: UITableViewCell {
weak var delegate : MyTableViewCellDelegate?
var data : Value!
private var counterValue = 0
#IBOutlet var lblInput : UILabel!
#IBOutlet var btnPrint : UIButton!
#IBOutlet var btnPlus : UIButton!
#IBOutlet var btnMinus : UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
#IBAction func DidPressPrint(){
self.data.number = counterValue
delegate?.DidPrint(Data: "\(data.number)")
print(data.number)
}
#IBAction func DidPressPlus(){
counterValue += 1
data.number = counterValue
self.lblInput.text = "\(data.number)"
}
#IBAction func DidPressMinus(){
if(counterValue > 0){
counterValue -= 1
data.number = counterValue
}
else{
counterValue = 0
data.number = 0
}
self.lblInput.text = "\(data.number)"
}
}
My Data Model
import Foundation
struct Value{
var number : Int
}
As #El Tomato suggested, you are not updating your data source, that's why your changes gets "forgotten" on scroll.
Try to move your didPressPlus, didPressMinus and didPressPrint in your ViewController class and redefine your table view delegate like below.
By passing the tag attributes to the buttons, you can then retrieve the index of the item pressed in the functions and edit the correct data source item.
Also remove the unnecessary MyTableViewCellDelegate.
class ViewController: UIViewController{
var numArray = [Value]()
var initialValue = 0
#IBOutlet weak var tableView : UITableView!
#IBOutlet weak var lblOutput : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
for _ in 0 ... 100 {
numArray.append(Value(number: initialValue))
}
self.lblOutput.text = "\(initialValue)"
tableView.delegate = self
tableView.dataSource = self
}
}
extension ViewController : UITableViewDelegate, UITableViewDataSource
{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? ControllerTableViewCell else {fatalError("Error in creating cells")}
let indexItem = indexPath.row
let valueItem = numArray[indexItem]
cell.lblInput.text = valueItem.number
cell.btnMinus.tag = indexItem
cell.btnMinus.addTarget(self, action: #selector(didPressMinus(_:)), for: .touchUpInside)
cell.btnPlus.tag = indexItem
cell.btnPlus.addTarget(self, action: #selector(didPressPlus(_:)), for: .touchUpInside)
cell.btnPrint.tag = indexItem
cell.btnPrint.addTarget(self, action: #selector(didPressPrint(_:)), for: .touchUpInside)
return cell
}
#objc private func didPressPlus(_ sender: UIButton) {
let dataIndex = sender.tag
if numArray.count < dataIndex { return }
let numArrayItem = numArray[dataIndex]
if (numArrayItem.number >= 0) {
numArray[dataIndex].number -= 1
}
tableView.reloadData()
}
#objc private func didPressMinus(_ sender: UIButton) {
let dataIndex = sender.tag
if numArray.count < dataIndex { return }
numArray[dataIndex].number += 1
tableView.reloadData()
}
#objc private func didPressPrint(_ sender: UIButton) {
let dataIndex = sender.tag
if numArray.count < dataIndex { return }
self.lblOutput.text = "\(numArray[dataIndex].number)"
}
}
In order to move the three methods in the ViewController you'll need to remove the two correspondent IBAction from the UITableViewCell class.
Also, remove the linkage with the ControllerTableViewCell actions.
Here is the resulting ControllerTableViewCell:
class ControllerTableViewCell: UITableViewCell {
#IBOutlet var lblInput : UILabel!
#IBOutlet var btnPrint : UIButton!
#IBOutlet var btnPlus : UIButton!
#IBOutlet var btnMinus : UIButton!
override func awakeFromNib() {
super.awakeFromNib()
}
}
Your TableView's numberOfRowsInSection is using numArray as a source (numArray.count) and so is your cellForRowAt function, but your cell functions are updating your 'data' variable. Your 'data' variable is locally defined to your tableView and gets reset every time it is activated (including when you scroll).
You need to update the numArray or some other global resource to make it work. This involves using indexpath of the cell value inside the cell functions, meaning you need a way to refer to indexPath inside the cell. This article explains how to use tags or delegates, https://fluffy.es/handling-button-tap-inside-uitableviewcell-without-using-tag/.
Here's a solution using the existing delegate.
import UIKit
import Foundation
var initialValue = 0
var numArray = Array(repeating: initialValue, count: 100)
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var lblOutput: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.lblOutput.text = "\(initialValue)"
tableView.delegate = self
tableView.dataSource = self
tableView.reloadData()
// Do any additional setup after loading the view.
}
}
extension ViewController : UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",for: indexPath) as? ControllerTableViewCell else{fatalError("Error in creating cells")}
cell.indexPath = indexPath
cell.delegate = self
cell.lblInput.text = String(numArray[indexPath.row])
return cell
}
}
extension ViewController : MyTableViewCellDelegate{
func DidPrint(Data: String) {
self.lblOutput.text = "\(Data)"
}
}
protocol MyTableViewCellDelegate : AnyObject {
func DidPrint(Data: String)
}
class ControllerTableViewCell: UITableViewCell {
weak var delegate : MyTableViewCellDelegate?
var indexPath : IndexPath?
private var counterValue = 0
#IBOutlet var lblInput : UILabel!
#IBOutlet var btnPrint : UIButton!
#IBOutlet var btnPlus : UIButton!
#IBOutlet var btnMinus : UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
#IBAction func DidPressPrint(){
delegate?.DidPrint(Data: "\(numArray[indexPath!.row])")
}
#IBAction func DidPressPlus(){
numArray[indexPath!.row] = numArray[indexPath!.row] + 1
self.lblInput.text = "\(numArray[indexPath!.row])"
}
#IBAction func DidPressMinus(){
if(numArray[indexPath!.row] > 0){
numArray[indexPath!.row] = numArray[indexPath!.row] - 1
}
else{
numArray[indexPath!.row] = 0
}
self.lblInput.text = "\(numArray[indexPath!.row])"
}
}

How can I get user to input text in a text field inside a xib cell in swift

I have created a xib cell with two textfields. The textfield are connected as IBoutlets to the xib swift file. The xib cell is registered on the view controller as a Nib. When I run the app on a simulator I cannot get the keyboard to show up. Secondly, the textfields are not editable at all, that is the cursor doesn't even show. I would like to get help with this as I have tried using a label the same thing happens. I'm just not sure how to fix this one. I'm not getting errors on build. I have installed IQKeyboardManager from cocoapods. Thanks in advance.
Heres the code:
import UIKit
class DictionaryCell: UITableViewCell {
#IBOutlet weak var DictBubble: UIView!
#IBOutlet weak var DictSymbolTextfield: UITextField!
#IBOutlet weak var SymbolMeaningTextfield: UITextView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Here is the view controller code:
import UIKit
import Firebase
class PersonalDreamDictionaryViewController: UIViewController, UITextViewDelegate {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var dictionaryTextfield: UITextField!
let db = Firestore.firestore()
var dreamDictionary: [DreamDictionary] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tableView.dataSource = self
tableView.delegate = self
title = K.Dictionary.appName
tableView.register(UINib(nibName: K.Dictionary.cellNibName, bundle: nil), forCellReuseIdentifier:
K.Dictionary.cellIdentifier)
loadDictionaryList()
}
func loadDictionaryList() {
db.collection(K.Fstore1.collectionName)
.order(by: K.Fstore1.date)
.addSnapshotListener{ (QuerySnapshot, error) in
self.dreamDictionary = []
if let e = error {
print("There was an issue retrieving data from Firestore. \(e)")
} else {
if let snapshotDocuments = QuerySnapshot?.documents {
for doc in snapshotDocuments {
//print(doc.data())
let data = doc.data()
if let symbolRetrieved = data[K.Fstore1.symbol] as? String, let meaningRetrieved = data[K.Fstore1.meaning] as? String {
let newDictList = DreamDictionary(mysymbol: symbolRetrieved, mymeaning: meaningRetrieved)
self.dreamDictionary.append(newDictList)
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
}
}
}
}
}
extension PersonalDreamDictionaryViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dreamDictionary.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let dictCell = tableView.dequeueReusableCell(withIdentifier: K.Dictionary.cellIdentifier, for: indexPath)
as! DictionaryCell
if let symbolInput = dictCell.DictSymbolTextfield.text, let meaningInput = dictCell.SymbolMeaningTextfield.text { db.collection(K.Fstore1.collectionName).addDocument(data: [
K.Fstore1.symbol: symbolInput,
K.Fstore1.meaning: meaningInput,
K.Fstore1.date: Date().timeIntervalSince1970
]) { (error) in
if let e = error {
print("There was an issue saving data to firesore, \(e)")
} else {
print("Successfully saved data.")
}
}
}
return dictCell
}
}
extension PersonalDreamDictionaryViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) {
print(indexPath.row)
}
}

swift, text in label doesn't change in viewDidAppear()

I'm new to IOS developtment but I'm programming an app where the user selects a row from a tableView (view 1). The text that the user selected is then displayed in a label on the same screen. When the user pushes the button the text from the label is stored in UserDefaults and the view changes to view 2. Here I have the viewDidAppear() method that gets the String out of the UserDefaults and changes the text of another Label on view 2.
Here is the code for view 1. The function that is called when the button is clicked is called schoolChosenClicked():
import UIKit
class ChooseSchool: UIViewController, UITableViewDataSource, UITableViewDelegate {
var SchoolNames = [String]()
#IBOutlet weak var table: UITableView!
var refresher: UIRefreshControl!
#IBOutlet weak var LabelSchoolName: UILabel!
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return SchoolNames.count
}
//Set the context
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = SchoolNames[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
LabelSchoolName.text = SchoolNames[indexPath.row]
}
override func viewDidLoad() {
super.viewDidLoad()
SchoolNames.append("Item")
SchoolNames.append("Item")
SchoolNames.append("Item")
SchoolNames.append("")
self.table.register(UITableViewCell.self, forCellReuseIdentifier: "cell");
self.table.dataSource = self
self.table.delegate = self
self.table.reloadData()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func schoolChosenClicked(_ sender: Any) {
UserDefaults.standard.set(LabelSchoolName.text, forKey: "chosenSchool")
}
}
Here is a picture of view 1
Here is the code for view 2
import UIKit
class Login: UIViewController {
#IBOutlet weak var LabelWelcome: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
if var schoolname = UserDefaults.standard.object(forKey: "chosenSchool") as? String
{
print("Das ist der Schoolname:" + schoolname+".")
LabelWelcome.text = "Willkommen bei deiner \(schoolname) App"
}
}
}
And here is the picture of the second view
In the 2nd picture you can see the Label that says "Name Anmelden". This text actually has to change to "Willkommen bei deiner (schoolname) App" but it does't or after a long period of time.
The value schoolname is well present and the print statement works fine but the LabelWelcome.text =... doesn't work or takes a long time. If I try to set the text in the viewDidLoad() method it works fine.
Do you know why or is there a method that i can call to update the screen?
Thank you,
Manuel
PS: Here is the screenshot of my login class (view 2)
Here is the first screenshot of my ChooseSchool class (view 1)
Here is the second screenshot of my ChooseSchool class (view 1
You need to select table cell or need to add text when clicking on the button:
#IBAction func schoolChosenClicked(_ sender: Any) {
LabelSchoolName.text = SchoolNames[indexPath.row]
UserDefaults.standard.set(LabelSchoolName.text, forKey: "chosenSchool")
}
After that still you getting the problem then add synchronize like this when you add your text in userdefault(This is not recommended):
UserDefaults.standard.set(LabelSchoolName.text, forKey: "chosenSchool")
UserDefaults.standard.synchronize()

Accessing Variables From a Different Swift Class

I have two swift files, each corresponding to a different view controller. I also have two classes, one for creating "Workout" objects and the other for holding these objects into an array. The workout class is a very simple class that just holds properties such as workout name, description, etc.
I am trying to access the array count of workoutList in my OverViewViewController.swift
Im a new developer and don't know how I would achieve this. Would I have to make a reference to the NewWorkoutViewController then try to grab the variable?
import UIKit
class OverViewViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 12
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "Hello"
return cell
}
}
import UIKit
class NewWorkoutViewController: UIViewController {
#IBOutlet weak var setStepper: UILabel!
#IBOutlet weak var repStepper: UILabel!
#IBOutlet weak var workoutName: UITextField!
#IBOutlet weak var workoutDescription: UITextField!
var workoutList = WorkoutList().listOfWorkouts
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func stepCounter(_ sender: UIStepper) {
if sender.tag == 1 {
setStepper.text = "\(Int(sender.value))"
}
if sender.tag == 2 {
repStepper.text = "\(Int(sender.value))"
}
}
#IBAction func addToWorkoutList(_ sender: UIButton) {
let workout = Workout(name: workoutName.text!, description: workoutDescription.text!, sets: Int(setStepper.text!)!, reps: Int(repStepper.text!)!)
workoutList.append(workout)
print(workoutList.count)
}
}
So the best way to do is create a model class name it as WorkOut with your required information. Then add the that object in array which you can define in your viewController class. Now you can pass that array information to another viewController class and can use it.

Can I add a new cell to a tableview, when I press a button in swift, with some text from a textfield?

so I have just started to learn swift, and I am a bit stuck at this.
I have this example with this table view . There are 3 texts inserted in an array from the code ... but I want to complete that array with some text that I put in a text field... -> #IBOutlet weak var inputMessage: UITextField! , and I want to add the text after I press a button : #IBAction func sendMsg(sender: AnyObject) ... I don't know how to create a cell in the table for each text I want to insert ...
It is possible to do that ... ? If yes, cand you give some tips ... ?
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
//table view
#IBOutlet weak var tableView: UITableView!
//input field
#IBOutlet weak var inputMessage: UITextField!
//text arrays
var textArray: NSMutableArray! = NSMutableArray()
//var input = inputMessage.text
//push the button
///when you press the button create a label and put in a cell view
#IBAction func sendMsg(sender: AnyObject) {
var input = inputMessage.text
self.textArray.addObject(input)
//make rows change their dimensions
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 44.0
self.textArray.addObject(input)
func viewDidLoad() {
super.viewDidLoad()
}
}
// the view did load function
override func viewDidLoad() {
super.viewDidLoad()
self.textArray.addObject("Before You Say I Can'T, Make Sure You'Ve Tried.")
self.textArray.addObject("-I'm a mirror. If you're cool with me, I'm cool with you, and the exchange starts. What you see is what you reflect. If you don't like what you see, then you've done something. If I'm standoffish, that's because you are.")
self.textArray.addObject("It seems like once people grow up, they have no idea what's cool.")
var input = inputMessage.text
//make rows change their dimensions
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 44.0
}
// the did received memory warning
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: Table View Delegate
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.textArray.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
cell.textLabel?.text = self.textArray.objectAtIndex(indexPath.row) as? String
return cell
}
}
Thank you!
Just reload your tableView after adding new element to textArray Like this:
self.textArray.addObject(input)
self.tableView.reloadData()
And you are adding your object into textArray two times.
So remove self.textArray.addObject(input)
And your action method will be:
#IBAction func sendMsg(sender: AnyObject) {
var input = inputMessage.text
//make rows change their dimensions
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 44.0
self.textArray.addObject(input)
tableView.reloadData()
}