ui label not printing the value - ios

Good morning. Why my code doesn't change the value of UILabel? When I click the UIButton the function has to multiply the Int value of the variable meters, filled as text, by 3 and show it in the UILabel.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var meters: UITextField!
#IBOutlet weak var button: UIButton!
#IBOutlet weak var answer: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func buttonClicked(_ sender: UIButton) {
answer.text = String(calculateNumber(meters: Int(meters.text ?? "") ?? 0));
}
func calculateNumber(meters : Int) -> Int {
let result = meters
print(result)
return result;
}
}

Check the code, it should work.
Check that meters are connected correctly.

Related

passing data to a specific label in another view controller, depending on the button pressed

I'm just starting out with swift and decided to create a calorie counting app to test my skills in which I am using an Api to get the nutrition data.
Pressing the add breakfast/lunch/dinner segues to a search view controller from which I pass the calories back.
I am using protocol delegate design pattern. I wanted to know how I could set it up so that when I press the add breakfast button, only the breakfast calorie label is updated and when I press add lunch or dinner, their calorie labels are updated accordingly. any help would be greatly appreciated! I posted the codes of my logViewController and SearchViewController
import UIKit
protocol DataDelegate {
func updateLogCalories(str: String?)
}
class SearchViewController: UIViewController,UITextFieldDelegate,CalorieManagerDelegate{
var delagate: DataDelegate?
#IBOutlet weak var searchTF: UITextField!
#IBOutlet weak var calorieLabel: UILabel!
#IBOutlet weak var foodNameLabel: UILabel!
var calorieManager = CalorieManager()
var logCals : String?
override func viewDidLoad() {
super.viewDidLoad()
calorieManager.delegate=self
searchTF.delegate=self
}
#IBAction func searchPressed(_ sender: Any) {
searchTF.endEditing(true)
print(searchTF.text!)
}
#IBAction func addButtonPressed(_ sender: UIButton) {
delagate?.updateLogCalories(str: logCals)
self.dismiss(animated: true, completion: nil)
}
class LogViewController: UIViewController{
var breakfastCal: String?
#IBOutlet weak var breakfastLabel: UILabel!
#IBOutlet weak var lunchLabel: UILabel!
#IBOutlet weak var totalCaloriesLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let navController = segue.destination as! UINavigationController
let destController = navController.topViewController as! SearchViewController
destController.delagate = self
}
#IBAction func addBreakfastPressed(_ sender: UIButton) {
}
#IBAction func addLunchPressed(_ sender: UIButton) {
}
}
extension LogViewController: DataDelegate{
func updateLogCalories(str: String?) {
breakfastLabel.text = str
}
}
If all of your buttons (breakfast, lunch, and dinner) trigger the addButtonPressed action, you need a way to tell which button was pressed, and a way to pass that information to the DataDelegate.
I suggest you put your buttons into an array:
#IBOutlet weak var breakfastButton: UIButton!
#IBOutlet weak var lunchButton: UIButton!
#IBOutlet weak var dinnerButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Populate our array of buttons so we can search for a button
buttons = [breakfastButton, lunchButton, dinnerButton]
}
Then modify your DataDelegate protocol to include a meal enum:
enum Meal: Int {
case breakfast = 0
case lunch = 1
case dinner = 2
}
protocol DataDelegate {
func updateLogCalories(str: String?, forMeal meal: Meal)
}
And set up your DataDelegate to implement the new method:
class MyDataDelegate: DataDelegate {
func updateLogCalories(str: String?, forMeal meal: Meal) {
let str = str ?? ""
print("updating calories with string \(str) for meal \(meal)")
}
}
Now modify your addButtonPressed method so it searches the array to figure out which button was pressed.
#IBAction func addButtonPressed(_ sender: UIButton) {
if let index = buttons.firstIndex(of: sender),
let meal = Meal(rawValue: index) {
print("Button at index \(index) pressed")
delegate.updateLogCalories(str: nil, forMeal: meal)
} else {
print("Can't find button or can't create enum.")
}
}

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

How to approach putting photos( and labels and buttons) into a Scroll View, having it lengthen every time a new photo is added in Storyboard

Right now on my Storyboard I have a View that I have a segue connecting to a scroll view. I want to make it so that the stuff (an image, label, buttons) on the first View on the Storyboard will go to the Scrollview once the segue button is pressed.
Is there a way that when I segue into the Scroll View the Scroll View will only be the size that it needs to be to fit the newly inputted information from the first View.
Also is there a way that I can save what was put into the Scroll View so the users can add to the scroll view to make it larger. I have Firebase in my app if I need to use that to save the Scroll View information.
Below are my two view controllers (I have no view controller for my scroll view but I can make one if I need it) and a screenshot of my storyboard if that will help!
import UIKit
class PhotoShareViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var contentTextView: UITextView!
#IBOutlet weak var thatTextField: UITextField!
#IBOutlet weak var thisTextField: UITextField!
var presenter: PhotoShareModuleInterface!
var image: UIImage!
#IBAction func thisUploadPhoto(_ sender: Any) {
if thisTextField.text != "" && thatTextField.text != "" {
performSegue(withIdentifier: "segue", sender: nil)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let photoShareLabelViewController = segue.destination as! PhotoShareLabelViewController
photoShareLabelViewController.thisString = thisTextField.text!
photoShareLabelViewController.thatString = thatTextField.text!
photoShareLabelViewController.imageLoaded = image
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
imageView.image = image
}
override var prefersStatusBarHidden: Bool {
return true
}
#IBAction func didTapCancel(_ sender: AnyObject) {
presenter.cancel()
presenter.pop()
}
#IBAction func didTapDone(_ sender: AnyObject) {
guard let message = thatTextField.text, !message.isEmpty else {
return
}
guard let messageOne = thisTextField.text, !messageOne.isEmpty else {
return
}
presenter.finish(with: image, content:message)
presenter.dismiss()
}
}
extension PhotoShareViewController: PhotoShareViewInterface {
var controller: UIViewController? {
return self
}
}
import UIKit
class PhotoShareLabelViewController: UIViewController {
#IBOutlet weak var thisLabel: UILabel!
#IBOutlet weak var thatLabel: UILabel!
#IBOutlet weak var thisButton: UIButton!
#IBOutlet weak var thatButton: UIButton!
#IBOutlet weak var changedImage: UIImageView!
var thisCounter = 0
var thatCounter = 0
#IBAction func pressedDoneButtonLabel(_ sender: Any) {
print("done")
}
var presenter: PhotoShareModuleInterface!
var imageLoaded: UIImage!
#IBAction func pressedThisButton(_ sender: Any) {
thisCounter += 1
print(thisCounter)
}
#IBAction func pressedThatButton(_ sender: Any) {
thatCounter += 1
print(thatCounter)
}
var thisString = String()
var thatString = String()
#IBAction func pressedButtonDone(_ sender: Any) {
print("done")
}
// #IBAction func pressedButtonCancel(_ sender: Any) {
// print("cancel")
// }
override func viewDidLoad() {
super.viewDidLoad()
thisLabel.text = thisString
thisButton.setTitle(thisString, for: UIControlState.normal)
thatLabel.text = thatString
thatButton.setTitle(thatString, for: UIControlState.normal)
changedImage.image = imageLoaded
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Thanks so much! Any and all help is appreciated!
It sounds like what you're trying to do was practically made for a UITableView or UICollectionView. UITableView is actually a subclass of UIScrollView for good reason – the content keeps expanding as needed. You will need to change your data model to be an array of whatever it is you want to display, but that should be fairly easy.
I'm not entirely sure what you're trying to achieve but if I'm correct you have a dynamically changing amount of photos?
If that's the case I would suggest you look at CollectionViews. This will handle the scroll view size for you and help formatting.
Consider these two links
https://developer.apple.com/documentation/uikit/uicollectionview
Great tutorial:
https://www.raywenderlich.com/136159/uicollectionview-tutorial-getting-started

Resources