Change the UILabel when a static variable changes - swift

I have a CartItem struct where I store the items that I show in a UITableView My UITableView is in CartViewController. I use custom cell for my table view. Here is my custom cell:
class CartItemCell: UITableViewCell {
#IBOutlet weak var productImage: UIImageView!
#IBOutlet weak var productName: UILabel!
#IBOutlet weak var productPrice: UILabel!
#IBOutlet weak var productTotalPrice: UILabel!
#IBOutlet weak var stepper: UIStepper!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
var cellIndex: Int?
var product: CartItem?{
didSet{
// change the cell in table view when first
// initialized and when stepper value is changed
.
.
.
}
#IBAction func stepperValueChanged(_ sender: UIStepper) {
CartItem.cartItems[self.cellIndex!].number = Int(sender.value)
self.product?.number = CartItem.cartItems[self.cellIndex!].number
}
}
In CartViewController I have totalPrice UILabel which gets its value from CartItem.totalPrice static variable. CartItem.totalPrice's value is calculated and changed every time UIStepper in my UITableViewCell is clicked. Here is the summary of CartViewController
class CartViewController: UIViewController{
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var cartLabel: UILabel!
#IBOutlet weak var totalPrice: UILabel!
var items = CartItem.cartItems
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.register(UINib(nibName: "CartItemCell", bundle: nil), forCellReuseIdentifier: "ReusableCell")
self.totalPrice.text = String(Int(CartItem.totalPrice))
tableView.reloadData()
}
}
extension CartViewController: UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableCell", for: indexPath) as! CartItemCell
cell.product = items[indexPath.item]
cell.cellIndex = indexPath.item
return cell
}
}
I want totalPrice label in the CartViewController changed every time CartItem.totalPrice is changed. I change the value of the CartItem.totalPrice in my CartItemCell
Thank you

Use delegate or closures to update value from tableviewcell to viewController
Protocol CartItemProtocol: AnyObject{
func valueUpdated()
}
class CartItemCell: UITableViewCell {
#IBOutlet weak var productImage: UIImageView!
#IBOutlet weak var productName: UILabel!
#IBOutlet weak var productPrice: UILabel!
#IBOutlet weak var productTotalPrice: UILabel!
#IBOutlet weak var stepper: UIStepper!
weak var delegate: CartItemProtocol?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
var cellIndex: Int?
var product: CartItem?{
didSet{
// change the cell in table view when first
// initialized and when stepper value is changed
.
.
.
}
#IBAction func stepperValueChanged(_ sender: UIStepper) {
CartItem.cartItems[self.cellIndex!].number = Int(sender.value)
self.product?.number = CartItem.cartItems[self.cellIndex!].number
self.delegate.valueUpdated()
}
}
And set delegate in cellforRow
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableCell", for: indexPath) as! CartItemCell
cell.product = items[indexPath.item]
cell.cellIndex = indexPath.item
cell.delegate = self
return cell
}
And Update label in delegate conformation
extension CartViewController:CartItemProtocl{
self.totalPrice.text = String(Int(CartItem.totalPrice))
}

Related

Swift UITableViewCell not showing Labels

I'm trying to create a custom cell view with some labels, I have created a subclass of UITableViewCell and connected the labels to it. Inside cellForRowAt method I dequeued the cell and cast it as YourCell subclass to access the labels and set text.
Setting class of cell to YourCell
However when running the app, nothing is showing up.
class YourCell: UITableViewCell {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
let array1 = ["Name1", "Name2","Name3","Name3"]
let array2 = ["1","2","3","4"]
let array3 = ["18","17","11","9"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tableView.delegate = self
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell") as! YourCell
cell.label1.text = array1[indexPath.row]
cell.label2.text = array2[indexPath.row]
cell.label3.text = array3[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array2.count
}
}
You have conformed the UITableViewDelegate protocol correctly, the only thing you are missing is to set up your datasource by including this line in your viewDidLoad.
tableview.dataSource = self

How to Add Shadow to TableView Without MasksToBound = False

When I add a shadow to my table view, it only shows if I have masksToBound = false as in picture 2. But it will look glitchy. Otherwise it looks fine scrolling up and down as in picture 1 but there's no shadow because I don't set it to false. Changing clipToBounds won't help either. My tableView changes height based on the input into the textField so I think adding a container view might be tricky.
How do I fix this? Is there a simple solution?
#IBOutlet weak var txtSearchBar: UITextField!
#IBOutlet weak var tblList: UITableView!
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var shadowView: UIView!
#IBOutlet weak var tblHeightConstraint: NSLayoutConstraint!
#IBOutlet weak var shadowHeightConstraint: NSLayoutConstraint!
#IBOutlet weak var collectionView: UICollectionView!
var majors:[String] = Array()
var results: [String] = Array()
var label = UILabel(frame: CGRect.zero)
var originalMajorsList = ["BIO 1AL", "BIO 1B", "BIO 1A", "MCB 118","..."]
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.collectionViewLayout = columnLayout
tblList.delegate = self
tblList.dataSource = self
txtSearchBar.delegate = self
txtSearchBar.addTarget(self, action: #selector(searchRecords(_ :)), for: .editingChanged)
txtSearchBar.layer.borderColor = UIColor.groupTableViewBackground.cgColor
txtSearchBar.layer.borderWidth = 1
txtSearchBar.layer.cornerRadius = 5
//**glitchy if masksToBounds = false**
tblList.layer.borderColor = UIColor.groupTableViewBackground.cgColor
tblList.layer.borderWidth = 1
tblList.layer.cornerRadius = 5
tblList.layer.shadowColor = UIColor.lightGray.cgColor
tblList.layer.shadowOffset = CGSize(width: -10, height: 10)
tblList.layer.shadowOpacity = 0.5
tblList.layer.shadowRadius = 50
tblList.layer.masksToBounds = false
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
txtSearchBar.resignFirstResponder()
return true
}
//MARK:- searchRecords
#objc func searchRecords(_ textField: UITextField) {
tblList.isHidden = false
self.majors.removeAll()
if textField.text?.count != 0 {
for major in originalMajorsList {
if let majorToSearch = textField.text{
let range = major.lowercased().range(of: majorToSearch, options: .caseInsensitive, range: nil, locale: nil)
if range != nil {
self.majors.append(major)
}
}
}
} else {
tblHeightConstraint.constant = 0
}
tblList.reloadData()
}
override func viewDidLayoutSubviews(){
tblHeightConstraint.constant = max(0, min(UIScreen.main.bounds.height * 0.4, tblList.contentSize.height))
}
//MARK:- UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return majors.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "major")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "major")
}
cell?.textLabel?.text = majors[indexPath.row]
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if !results.contains(majors[indexPath.row]) {
results.append(majors[indexPath.row])
}
textField.text = ""
tableView.isHidden = true
collectionView.reloadData()
}

in the Table view I want to add some images but when I run it doesn't show and I already import the images in assets.xcassets

I already make an array to access the picture.. Can someone help? thanks
Here is my code:
import UIKit
class MainMenuViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let labeltitle = ["Acme De la Vie Tee", "Anti Social Social Club Black Hoodie", "CDG Play Gold Black Tee"]
let labelprice = [("RM 240"), ("RM 305"), ("RM 418")]
let myImage = [UIImage(named: "adlv1"), UIImage(named: "assc"), UIImage(named: "cdg1")]
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return labeltitle.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MainMenuTableViewCell
cell.label11?.text = labeltitle[indexPath.row]
cell.label2?.text = labelprice[indexPath.row]
cell.myImage.image = self.myImage[indexPath.row]
return cell
}
}
Here is my code for MainMenuTableViewCell
import UIKit
class MainMenuTableViewCell: UITableViewCell {
#IBOutlet weak var label11: UILabel!
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var myImage: UIImageView!
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
}
}
you need to register your tableviewcell in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.register(MainMenuTableViewCell.self, forCellReuseIdentifier: "cell")
}
Apple Documentation
More Info
Did u add constraint ?
Select to viewController and do reset the suggested constraint and im sure it will be solved
cell.myImage.image = self.myImage[indexPath.row]
try to change your image Array name

Why my Data model aren't upload in my tableviewcontroller

I don't know why I can't view my pets in the table.
Few days ago the app is working perfect but when I updated the last version of Xcode the app crashed, I can't see the data whet the App run.
I new developer in swift
Help me, please.
------------------------------Model------------------------
import UIKit
struct InfoPet{
let PetPicture: String
let PetBackground: String
let PetName: String
let PetAge: String
static func InfoPets() -> [InfoPet]{
let pet1 = InfoPet(PetPicture: "Drako", PetBackground: "Background Can", PetName: "Drako", PetAge: "2 years old")
let pet2 = InfoPet(PetPicture: "Lucky", PetBackground: "Background Cat", PetName: "Lucky", PetAge: "3 years old")
return [pet1, pet2]
}
}
-----------------------TableViewController----------------
class PetsTableViewController: UITableViewController {
// MARK: - Global Var
var pets: [InfoPet] = InfoPet.InfoPets()
// MARK: - UITableViewDataSource
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pets.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PetCell", for: indexPath) as! PetsTableViewCell
let pet = pets[indexPath.row]
cell.pet = pet
return cell
}
// MARK: - UITableViewDalegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
-----------------------tableViewCell-----------------------
class PetsTableViewCell: UITableViewCell {
#IBOutlet weak var ImgPhotoPet: UIImageView!
#IBOutlet weak var ImgBackgroundPet: UIImageView!
#IBOutlet weak var LblNamePet: UILabel!
#IBOutlet weak var LblAgePet: UILabel!
var pet: InfoPet!{
didSet{
updateUI()
}
}
func updateUI() {
ImgBackgroundPet.image = UIImage(named: pet.PetBackground)
ImgPhotoPet.image = UIImage(named: pet.PetPicture)
ImgPhotoPet.layer.cornerRadius = 10.0
ImgPhotoPet.layer.masksToBounds = true
LblNamePet.text = pet.PetName
LblAgePet.text = pet.PetAge
}
}
Add Cell Identifier as "PetCell"
and add viewDidLoad method in PetsTableViewController class.
create IBOutlet of the table view.
#IBOutlet weak var tableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableview.dataSource = self
tableview.delegate = self
}

Implement delegate method in Table View

IĀ“have a table view with a custom cell. In this cell I have two buttons that are used for counting. One pluss button, and one minus button. These buttons should increment and decrease a counterLabel with 1.
I have done this in a project I did a long time ago, but then I used extensions, witch I don't do in this project. My problem is that I cannot figure out how to implement the delegate method that I used in the previous project.
I will show the code I'm trying, as an extension. This gives the error "Ambiguous reference to member 'tableView(_:numberOfRowsInSection:)'".
How should I correctly implement the delegate?
Main View Controller
import UIKit
class MainViewController: UIViewController, UITableViewDelegate {
let staticList: [ListItem] =
[
ListItem(item1: "item1", item2: "item2", item3: "item3")]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return staticList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell
cell = tableView.dequeueReusableCell(withIdentifier: "MenuCell", for: indexPath)
if let customCell = cell as? MenuCell
{
let itemIndex = indexPath.row
let listItem = staticList[itemIndex]
customCell.item1Label.text = listItem.item1
customCell.item2Label.text = listItem.item2
customCell.item3Label.text = listItem.item3
customCell.counterLabel.text = "\(listItem.count)"
}
return cell
}
}
#IBOutlet weak var mainTableView: UITableView!
}
extension MainViewController: CountDelegate {
func didAddItemCell(cell: MainCell) {
let indexPath = tableView.indexPath(for: cell)!
staticList[indexPath.row].count += 1
cell.countLabel.text = "\(staticList[indexPath.row].count)"
}
func didSubtractItemCell(cell: MenuCell) {
let indexPath = tableView.indexPath(for: cell)!
if staticList[indexPath.row].count > 0 {
staticList[indexPath.row].count -= 1
cell.countLabel.text = "\(staticList[indexPath.row].count)"
}
}
}
Table View Cell file
import Foundation
import UIKit
protocol CountDelegate: NSObjectProtocol {
func didAddItemCell(cell: MainCell)
func didSubtractItemCell(cell: MainCell)
}
class MenuCell : UITableViewCell
{
#IBOutlet weak var item1Label: UILabel!
#IBOutlet weak var item2Label: UILabel!
#IBOutlet weak var item3Label: UILabel!
#IBOutlet weak var counterLabel: UILabel!
#IBOutlet weak var minusButton: UIButton!
#IBOutlet weak var plusButton: UIButton!
weak var delegate: CountDelegate?
#IBAction func minusButton(_ sender: UIButton)
{
delegate?.didAddItemCell(cell: self)
}
#IBAction func plusButton(_ sender: UIButton)
{
delegate?.didSubtractItemCell(cell: self)
}
}
The numberOfRowsInSection and cellForRowAt methods are not part of the UITableViewDelegate protocol but the UITableViewDataSource protocol. You therefore need to change add that protocol like this:
class MainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
You will also need to implement this as well:
func numberOfSections(in tableView: UITableView) -> Int {
return 1 // Or whatever it should be
}