Swift Stepper Action that changes UITextField and UILabel within same cell - ios

I am using a function to build my custom cell. the function used to create the cell is "makeMyList". The stepper I have successfully increments and decrements the itemQuantity textField. The trouble I am having comes with updating the "itemPrice" label. I want itemPrice.text to be quantity * price and update dynamically as the quantity either goes up or down dynamically.
Could someone possibly help me with how to get this to happen?
Thank you in advance!
class MyListTableViewCell: UITableViewCell
{
#IBOutlet weak var itemPrice: UILabel!
#IBOutlet weak var itemName: UILabel!
#IBOutlet weak var itemQuantity: UITextField!
#IBOutlet weak var stepper: UIStepper!
#IBAction func itemQuantityStepper(sender: UIStepper)
{
self.itemQuantity.text = Int(sender.value).description
}
override func awakeFromNib() {
super.awakeFromNib()
}
func makeMyList(myItem: MyList)
{
self.itemName.text = myItem.MyItemName
self.itemPrice.text = String(stepper.value * Double(myItem.MyItemPrice))
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}

For anyone who has the same issue. Here is the answer to my own question.
Hope it helps!
class MyListTableViewCell: UITableViewCell
{
#IBOutlet weak var itemPrice: UILabel!
#IBOutlet weak var itemName: UILabel!
#IBOutlet weak var itemQuantity: UITextField!
#IBOutlet weak var stepper: UIStepper!
var price: Float = 0.0
var quantity: Int = 1
override func awakeFromNib() {
super.awakeFromNib()
}
func makeMyList(myItem: MyList)
{
self.itemName.text = myItem.MyItemName
self.itemPrice.text = myItem.MyItemPrice
price = Float(myItem.MyItemPrice)
}
#IBAction func itemQuantityStepper(sender: UIStepper)
{
quantity = Int(sender.value)
self.itemQuantity.text = String(quantity)
self.itemPrice.text = price * Float(quantity)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}

Related

How to implement event on click in button inside in a tableView to show other element?

I have a tableView with action buttons, one of them are hide until the user click the other button, I was looking how to do that and I found that I have to implement a delegate like the code below:
Class TableViewCell:
import UIKit
import FLAnimatedImage
protocol OnButtonsClickDelegate:AnyObject{
func onBtnDownloadClick(cell: ListadoTableViewCell)
}
class ListadoTableViewCell: UITableViewCell {
#IBOutlet weak var lblAnterior: UILabel!
#IBOutlet weak var lblCompras: UILabel!
#IBOutlet weak var lblDevolucion: UILabel!
#IBOutlet weak var lblSaldo: UILabel!
#IBOutlet weak var lblAbonos: UILabel!
#IBOutlet weak var lblNuevo: UILabel!
#IBOutlet weak var lblDiferido: UILabel!
#IBOutlet weak var lblCliente: UILabel!
#IBOutlet weak var lblNombreCliente: UILabel!
#IBOutlet weak var spinner: FLAnimatedImageView!
#IBOutlet weak var btnDowload: UIButton!
#IBOutlet weak var btnShare: UIButton!
var onButtonsClickDelegate : OnButtonsClickDelegate!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
#IBAction func onBtnDownloadClick(_ sender: AnyObject){
onButtonsClickDelegate.onBtnDownloadClick(cell: self)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Class Controller:
class ListadoController: NavigationViewController, UITableViewDelegate, UITableViewDataSource, RefreshScrollViewDelegate,OnButtonsClickDelegate {
#IBOutlet weak var tableView: RefreshTableView!
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellListado") as! ListadoTableViewCell
let r = data[indexPath.row]
let compras = Functions.stringToFloat(str: r.compras)
let comprasn = Functions.stringToFloat(str: r.comprasn)
let abonos = Functions.stringToFloat(str: r.abonos)
let diferido = Functions.stringToFloat(str: r.diferido)
let saldomov = Functions.stringToFloat(str: r.saldomov)
cell.lblAnterior.text = Functions.moneyFormat(n: saldomov - compras - comprasn)
cell.lblCompras.text = Functions.moneyFormat(n: compras)
cell.lblDevolucion.text = Functions.moneyFormat(n: 0.0)
cell.lblSaldo.text = Functions.moneyFormat(n: saldomov - comprasn)
cell.lblAbonos.text = Functions.moneyFormat(n: abonos) + ""
cell.lblNuevo.text = Functions.moneyFormat(n: saldomov - comprasn - abonos) + ""
cell.lblDiferido.text = Functions.moneyFormat(n: diferido) + ""
cell.lblCliente.text = r.nombre.capitalized
cell.lblNombreCliente.text = r.cvecte
cell.onButtonsClickDelegate = self
if indexPath.row == data.count - 1 {
if (!last && !loading) {
loadData(page: currentPage)
}
}
return cell
}
func onBtnDownloadClick(cell: ListadoTableViewCell) {
cell.btnShare.isHidden = false
}
}
The problem is that it does not work correctly. When the user clicks the button, the other element is displayed but not only in the selected row, but also in other rows as well, how can I solve this problem?
The cell is being re-used and whatever is the state of that cell will still be there, in which case, try adding this to ListadoTableViewCell:
override func prepareForReuse() {
super.prepareForReuse()
btnShare.isHidden = true
}
You should try to save the state of the cell when you press the download button so that when the reloadData of the TableView is performed and the cellForRowAt function is called, the state of the changes in the cells is preserved, in your case the share button is shown if the download button has previously been pressed.
Here there is a project from my Github that make the functionality you need by applying MVVM Pattern https://github.com/JLPenaLopez/MyFiles I hope this helps you
This is a demostration: https://github.com/JLPenaLopez/MyFiles/blob/master/MyFilesGif.gif
I solved using an answer from another post:
Button action in custom UITableViewCell affects other cells
Thank you for your help.

Calling a function that will hide a button from another class - swift

I'm trying to create an IMDB-ish movie application where when the user doesn't login and presses a Skip button, a Favorite (add a movie to favourites) button would dissappear.
The LandingViewController is where the Skip button is and the MovieTableViewCell is where all the data is presented.
What must I do so that the hide action will work inside the function? what's the logic behind this? what am I missing?
Kindly check the below comments in the code. thanks !
import UIKit
class LandingViewController: UIViewController {
#IBOutlet weak var skipButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func didTapSkip(_ sender: Any) {
MovieTableViewCell().hideButton()
}
import UIKit
class MovieTableViewCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var ratingLabel: UILabel!
#IBOutlet weak var languageLabel: UILabel!
#IBOutlet weak var releaseYearLabel: UILabel!
#IBOutlet weak var posterImage: UIImageView!
#IBOutlet weak var favoriteButton: UIButton?
override func awakeFromNib() {
super.awakeFromNib()
favoriteButton?.isHidden = true // works here for some reason
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func hideButton() {
favoriteButton?.isHidden = true // doesn't work and If I unwrap it, the app will crash, because it will find the buttton as NIL for some reason
print("hidebutton") // the print works so the function works when the skip is pressed
}
Try using NSUserDefaults
In LandingViewController
#IBAction func didTapSkip(_ sender: Any) {
UserDefaults.standard.set(true, forKey: "didSkip")
}
In MovieTableViewCell
override func awakeFromNib() {
super.awakeFromNib()
if UserDefaults.standard.bool(forKey: "didSkip") {
favoriteButton?.isHidden = true
} else {
favoriteButton?.isHidden = false
}
}

"fatal error" when calling tableView.reloadData(), the tableView is properly connected

I am trying to dynamically update a tableView while the program is running. I believe I have updated the array that the data loads from correctly, but when I press the button that calls self.eventTable.reloadData() I receive the error:
fatal error: unexpectedly found nil while unwrapping an Optional value
Here is the relevant code:
View Controller:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
//Timer view
#IBOutlet weak var playButton: UIBarButtonItem!;
#IBOutlet weak var pauseButton: UIBarButtonItem!;
#IBOutlet weak var refreshButton: UIBarButtonItem!;
#IBOutlet weak var timerLabel: UILabel!
var counter = 0
var timer = Timer()
var isTimerRunning = false
//testing view container
var viewShowing = 1;
override func viewDidLoad() {
// Do any additional setup after loading the view, typically from a nib.
pauseButton.isEnabled = false
hideAll();
self.basicContainer.isUserInteractionEnabled = true;
self.basicContainer.isHidden = false;
self.timerLabel.text = String("00:00:00");
eventTable.dataSource = self
eventTable.delegate = self
super.viewDidLoad()
loadEvents(event: "timer start")
}
...
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Add table to keep track of events
#IBOutlet weak var eventTable: UITableView!
var eventData = [Session]()
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return eventData.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier") as! eventTableViewCell
let event = eventData[indexPath.row]
cell.eventLabel.text = event.session
return cell
}
private func loadEvents(event: String) {
guard let event1 = Session(session: event) else {
fatalError("Unable to instantiate event")
}
eventData += [event1]
DispatchQueue.main.async() {
self.eventTable.reloadData()
}
}
func testPrint() {
loadEvents(event: "testing cell adding")
//self.eventTable.reloadData()
viewWillAppear(false)
print("This is a test print");
}
}
The function works fine when it is called in ViewDidLoad(), but not when it is called by the button in another class ("This is a test print" prints to console so I know the button call is going through).
Expected behavior is the tableView (eventTable) reloading showing two cells, "timer start" and "testing cell adding" (ideally with "testing cell adding" being at the top).
Also want to emphasize that eventTable is connected to the storyboard, which seems to be a common problem on here.
Here is the Session.swift file and the eventTableViewCell.swift file if those are helpful:
Session.swift
import Foundation
import UIKit
class Session {
//MARK: Properties
var session: String
//MARK: Initialization
init?(session: String) {
guard !session.isEmpty else {
return nil
}
self.session = session
}
}
eventTableViewCell.swift
import Foundation
import UIKit
class eventTableViewCell: UITableViewCell {
//MARK: Properties
#IBOutlet weak var eventLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Thanks!
Edit: The ViewController from where I call testPrint().
import UIKit
class BasicViewController: UIViewController {
var VC = ViewController();
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.
}
//Basic buttons
#IBOutlet weak var warmButton: UIButton!
#IBOutlet weak var dryButton: UIButton!
#IBOutlet weak var stimulateButton: UIButton!
#IBOutlet weak var controlButton: UIButton!
#IBOutlet weak var bedButton: UIButton!
#IBOutlet weak var tempButton: UIButton!
#IBOutlet weak var pulseButton: UIButton!
#IBOutlet weak var ecgButton: UIButton!
#IBOutlet weak var apgarButton: UIButton!
#IBOutlet weak var helpButton: UIButton!
//APGAR options
#IBOutlet weak var skinColor: UIButton!
#IBOutlet weak var pulse: UIButton!
#IBOutlet weak var grimace: UIButton!
#IBOutlet weak var flexion: UIButton!
#IBOutlet weak var respiratoryEffort: UIButton!
#IBAction func warmButton(sender: AnyObject) {
VC.testPrint();
}
}
It would seem that you are all right in stating that I am instantiating a new ViewController which is causing the issue. How should I go about fixing this? Fairly new to Swift
I think, your problem is in this lines of codes:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier") as! eventTableViewCell
let event = eventData[indexPath.row]
cell.eventLabel.text = event.session
return cell
}
Can you check the cell identifier is same as your cell identifier
And number of rows in eventData array

Getting Nil While Trying to Set Class Label Property | UITableView

I keep getting unexpectedly found nil while unwrapping an Optional value when I run this code.
What I am trying to do is get the first property in an array of objects so I use .map to get the first property which is "workoutName"
Then I try to set the label in the CellData class to this value but keep getting that it found nil.
I appreciate all help I can get.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var workoutName = workouts.map { $0.workoutName }
let cell = CellData()
cell.workoutNameLabel.text! = workoutName[indexPath.row]
return cell
}
Cell Data Class
import UIKit
class CellData: UITableViewCell {
#IBOutlet weak var workoutNameLabel: UILabel!
#IBOutlet weak var numberOfSetsNumberLabel: UILabel!
#IBOutlet weak var numberOfRepsNumberLabel: UILabel!
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
}
}
I would set class variable into CellData class and set it in awakeFromNib since awakeFromNib won't happen before the cellForRow is finished, so you can be almost 100% sure that the label will be nil.. try this:
import UIKit
class CellData: UITableViewCell {
//someLableValue string
var labelValueText: String?
#IBOutlet weak var workoutNameLabel: UILabel!
#IBOutlet weak var numberOfSetsNumberLabel: UILabel!
#IBOutlet weak var numberOfRepsNumberLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
workoutNameLabel.text = labelValueText
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
then you jsut set the variable labelValueText in cellForRowMethod in UITableViewController class

Swift delegate not working

I have a stepper in my ViewController that controls the value of a variable in my UIView. When I reset the variables to 0 in my UIView, I also want the stepper and label to reset, but they won't. I tried using a delegate, but am getting an error. Thanks in advance!
ViewController:
protocol CircleViewDelegate: class {
func updateStepper(view: CircleView)
}
class ViewController: UIViewController, CircleViewDelegate {
var colors = CircleView()
#IBOutlet weak var circleView1: CircleView!
#IBOutlet weak var blueStepper: UIStepper!
#IBOutlet weak var greenStepper: UIStepper!
#IBOutlet weak var redStepper: UIStepper!
#IBOutlet weak var redValue: UILabel!
#IBOutlet weak var greenValue: UILabel!
#IBOutlet weak var blueValue: UILabel!
var circleViewDelegate: CircleView!
override func viewDidLoad() {
super.viewDidLoad()
circleViewDelegate!.delegate = self
}
func updateStepper(view: CircleView) {
redStepper.value=0.0;
greenStepper.value=0.0;
blueStepper.value=0.0;
}
#IBAction func stepperChange(sender: UIStepper) {
circleView1.redd1 = Int(redStepper.value);
redValue.text = Int(sender.value).description;
}
#IBAction func stepperChange1(sender: UIStepper) {
circleView1.greenn1 = Int(greenStepper.value);
greenValue.text = Int(sender.value).description;
}
#IBAction func stepperChange2(sender: UIStepper) {
circleView1.bluee1 = Int(blueStepper.value);
blueValue.text = Int(sender.value).description;
}
}
UIView:
class CircleView: UIView {
var redd1 = 0
var greenn1 = 0
var bluee1 = 0
weak var delegate: CircleViewDelegate?
func updateStepper() {
delegate?.updateStepper(self)
}
func game() {
if(redd1==Int(red1) && greenn1==Int(green1) && bluee1==Int(blue1)) {
redd1 = 0;
green1 = 0;
blue1 = 0;
updateStepper()
}
}
}
Try this:
override func viewDidLoad() {
super.viewDidLoad()
circleView1.delegate = self
}
func updateStepper(view: CircleView) {
redStepper.value = 0.0
greenStepper.value = 0.0
blueStepper.value = 0.0
stepperChange(redStepper)
stepperChange(greenStepper)
stepperChange(blueStepper)
}
Instead of assigning the delegate like this circleViewDelegate!.delegate = self in viewDidLoad try circleView1.delegate = self

Resources