So I currently have a tableView in a ViewController called GearComponentViewController
that has custom tableViewCells that have a UIStepper in them to control a quantity label and conforms to the custom protocol Stepper
.
protocol Stepper {
func stepperWasPressed(didIncrease: Bool, namePassed: String, userindexPath: Int)
}
And here's the code for the GearComponentTableViewCell
:
class GearComponentTableViewCell: UITableViewCell {
var mainVC = GearComponentViewController()
var tableViewCellPosition: Int! = nil
// Image
@IBOutlet weak var itemImage: UIImageView!
// Name
@IBOutlet weak var itemName: UILabel!
// Weight
@IBOutlet weak var itemWeight1: UILabel!
@IBOutlet weak var itemWeight2: UILabel!
// Quanity
@IBOutlet weak var itemQuanity: UILabel!
@IBAction func stepperPressed (_ sender: UIStepper!){
if (sender.value == 1) {
print("up and item: \(itemName.text!)");
sender.value = 0
mainVC.stepperWasPressed(didIncrease: true, namePassed: itemName.text!, userindexPath: tableViewCellPosition)
} else if (sender.value == -1) {
print("down and item: \(itemName.text!)");
sender.value = 0
mainVC.stepperWasPressed(didIncrease: false, namePassed: itemName.text!, userindexPath: tableViewCellPosition)
}
}
// Notes
@IBOutlet weak var itemNotes: UILabel!
}
It detects if the user clicked on the plus button or the minus button on the stepper and calls the function from the protocol stepperWasPressed()
Finally here's the code for the mainVC
referenced:
extension GearComponentViewController: Stepper {
func refreshTableViewCell() {
print("arrayPosition: \(arrayPosition)")
// gearTableView.reloadData()
}
func stepperWasPressed(didIncrease: Bool, namePassed: String, userindexPath: Int) {
if didIncrease {
arrayPosition = userindexPath
print("arrayPosition: \(arrayPosition)")
// itemArray[userindexPath].quanity += 1
print("userindexPath: \(userindexPath) -- namePassed: \(namePassed) -- didIncrease: \(didIncrease)")
print("increase selected")
refreshTableViewCell()
}else {
arrayPosition = userindexPath
print("arrayPosition: \(arrayPosition)")
// itemArray[userindexPath].quanity -= 1
print("userindexPath: \(userindexPath) -- namePassed: \(namePassed) -- didIncrease: \(didIncrease)")
print("decrease selected")
refreshTableViewCell()
}
}
}
When I try to do either itemArray[userindexPath].quanity += 1
or itemArray[userindexPath].quanity -= 1
I'm getting the error listed in the title, but to be even able to call that part of the function the count of my itemArray has to be greater than zero/empty because I'm being presented a cell with a stepper in it.
Full GearComponentViewController:
import UIKit
class GearComponentViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var arrayPosition: Int = 0
// Data Sources
var itemArray: [GearItem] = []
var totalWeight1: Int = 0
var totalWeight2: Int = 0
var totalItems: Int = 0
// Weight Label Outlets
@IBOutlet weak var weight1LabelOutlet: UILabel!
@IBOutlet weak var weight2LabelOutlet: UILabel!
// Item Count Label Outlet
@IBOutlet weak var totalCountLabelOutlet: UILabel!
// TableView Outlet
@IBOutlet weak var gearTableView: UITableView!
// Bar Button Item
@IBAction func addItemPressed(_ sender: Any) {
presentAlert()
}
// View Did Load
override func viewDidLoad() {
super.viewDidLoad()
gearTableView.dataSource = self
gearTableView.delegate = self
print("Gear Component View Controller successfully loaded.")
updateUI()
// Do any additional setup after loading the view.
}
//MARK: - UI Updater
func updateUI() {
addTotalWeight()
addAllItems()
}
// Adding Total Weight
func addTotalWeight() {
var addedWeight1: Int = 0
var addedWeight2: Int = 0
for item in itemArray {
addedWeight1 += item.weight1 * item.quantity
addedWeight2 += item.weight2 * item.quantity
}
totalWeight1 = addedWeight1
totalWeight2 = addedWeight2
weight1LabelOutlet.text = String("\(totalWeight1)")
weight2LabelOutlet.text = String("\(totalWeight2)")
}
// Item Count
func addAllItems() {
var addedValue: Int = 0
for item in itemArray {
addedValue += item.quantity
}
totalItems = addedValue
totalCountLabelOutlet.text = String("\(totalItems)")
print("Total items: \(totalItems)")
}
//MARK: - Alert
func presentAlert() {
let alertController = UIAlertController(title: "Add Item", message: "Enter item info here", preferredStyle: .alert)
// AlertController Textfields
alertController.addTextField { (textField) in
textField.placeholder = "Name"
}
alertController.addTextField { (textField) in
textField.placeholder = "Weight 1"
textField.keyboardType = .decimalPad
}
alertController.addTextField { (textField) in
textField.placeholder = "Weight 2"
textField.keyboardType = .decimalPad
}
alertController.addTextField { (textField) in
textField.placeholder = "Quanity"
textField.keyboardType = .decimalPad
}
alertController.addTextField { (textField) in
textField.placeholder = "Notes"
}
// AlertController Actions
let continueAction = UIAlertAction(title: "Add", style: .default) { [self, weak alertController] _ in
guard let textFields = alertController?.textFields else { return }
if let userItemName = textFields[0].text,
let userItemWeight1 = textFields[1].text,
let userItemWeight2 = textFields[2].text,
let userItemQuanity = textFields[3].text,
let userItemNotes = textFields[4].text {
print("Name: \(userItemName)")
print("Item Weight 1: \(userItemWeight1)")
print("Item Weight 2: \(userItemWeight2)")
print("Item Quantity: \(userItemQuanity)")
print("Item Notes: \(userItemNotes)")
let userSubmittedItem = GearItem(itemName: userItemName, itemImage: UIImage(systemName: "photo.on.rectangle.angled")!, itemWeight1: Int(userItemWeight1) ?? 0, itemWeight2: Int(userItemWeight2) ?? 0, itemQuantity: Int(userItemQuanity) ?? 1, itemNotes: userItemNotes ?? "", creationPosition: itemArray.count + 1)
self.itemArray.append(userSubmittedItem)
gearTableView.reloadData()
updateUI()
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
cancelAction.setValue(UIColor.red, forKey: "titleTextColor")
alertController.addAction(continueAction)
alertController.addAction(cancelAction)
self.present(alertController,
animated: true)
}
//MARK: - TableView Protocol Functions
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = gearTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! GearComponentTableViewCell
cell.itemName.text = itemArray[indexPath.row].name
cell.itemImage.image = itemArray[indexPath.row].image
cell.itemWeight1.text = String("\(itemArray[indexPath.row].weight1)")
cell.itemWeight2.text = String("\(itemArray[indexPath.row].weight2)")
cell.itemQuanity.text = String("\(itemArray[indexPath.row].quantity)")
cell.itemNotes.text = itemArray[indexPath.row].notes
cell.tableViewCellPosition = indexPath.row
return cell
}
//MARK: - Swipeable TableViewCell
private func deleteItem(_ indexPath: IndexPath) {
itemArray.remove(at: indexPath.row)
gearTableView.reloadData()
updateUI()
print("Item Deleted")
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let action = UIContextualAction(style: .normal, title: "Delete") { [weak self] (action, view, completionHandler) in
self?.deleteItem(indexPath)
completionHandler(true)
}
action.backgroundColor = .systemRed
return UISwipeActionsConfiguration(actions: [action])
}
}
extension GearComponentViewController: Stepper {
func refreshTableViewCell() {
print("arrayPosition: \(arrayPosition)")
// itemArray[arrayPosition].quantity += 1
// gearTableView.reloadData()
}
func stepperWasPressed(didIncrease: Bool, namePassed: String, userindexPath: Int) {
if didIncrease {
arrayPosition = userindexPath
print("arrayPosition: \(arrayPosition)")
// itemArray[userindexPath].quanity += 1
print("userindexPath: \(userindexPath) -- namePassed: \(namePassed) -- didIncrease: \(didIncrease)")
print("increase selected")
refreshTableViewCell()
}else {
arrayPosition = userindexPath
print("arrayPosition: \(arrayPosition)")
// itemArray[userindexPath].quanity -= 1
print("userindexPath: \(userindexPath) -- namePassed: \(namePassed) -- didIncrease: \(didIncrease)")
print("decrease selected")
refreshTableViewCell()
}
}
}
And here's an image of what my app looks like right now for reference.