Yann Morin Charbonneau
Yann Morin Charbonneau

Reputation: 177

How to access an object inside a ViewController from within a TableViewCell

I am fairly new at coding in swift and I've been trying to find a solution to my problem for the past couple days, and am not able to.

I have a class named userData with various properties:

class UserData {
    var name: String
    var age: Int
    var credits: Int = 1
    ...

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

Inside the viewController.swift I have declared an object of this class:

...
var user = UserData(name: "testing", age: 5)
...

Inside the same viewController I have a UITableView with a few UITableViewCells. In every cell there is a UIStepper

Using the UIStepper from a cell I want to increment or decrement the property credits of my object user that sits inside the viewController.swift, and do that from within the tableViewCell.swift file

From what I can find, I think I should use a delegate but I can figure out how to implement it.

More information: Pardon the art work, I am not an artist...

my app image

The user has a set amount of ants available to work (this number is a property of my object user). There is also a property for the amount of ants currently working ('ants used' in my screen shot).

At first, the white label on top says '0/5' (Meaning the user has 5 available ants to work but none are currently working).

When the user increments the stepper for 'scavenger ants', the white label on top should say '1/5' (Meaning that there is currently 1 ant working out of 5 that are available).

What I want to do, is that when the user clicks on a stepper, the user's property for the 'ants currently working' increments or decrements appropriately.

Thank you

Upvotes: 1

Views: 95

Answers (2)

Augusto Dias Noronha
Augusto Dias Noronha

Reputation: 864

Set that logic up in the view controllers' cellForRowAt.

When setting up the cell, you can add a function inside your view controller as the target every-time the UIStepper value changes:

// inside cellForRowAtIndexPath:
cell.addTarget(self, action: #selector(doSomething(sender:), for: .valueChanged)

Inside doSomething you set up the logic for updating your model.

func doSomething(sender: UIStepper) {
    // do stuff here
}

Edit with an example of the delegate pattern which would be a better solution, for future readers.

First create a protocol:

protocol StepperCellDelegate {
    func didChangeValueForStepper(inCell: Cell, whateverInfoYouWantHere:...)
    func otherUsefulFunctions(...)
}

In your cell class, set a target/action for when your value is changed:

// inside the cell's initialization (`init(style:reuseIdentifier:)`
self.addTarget(self, action: #selector(valueChanged(sender:), for: .valueChanged)

Your cell also needs a delegate property:

weak var stepperCellDelegate: StepperCellDelegate?

doSomething would look something like this:

func valueChanged(sender: UIStepper) {
    stepperCellDelegate?.didChangeValueForStepper(inCell: self, ...)
}

Your ViewController will implement the protocol

extension MyViewController: StepperCellDelegate {
    func didChangeValueForStepper(inCell: Cell, whateverInfoYouWantHere:...) {
        // implementation here
    }

    func otherUsefulFunctions(...){
        // implementation here
    }
}

And inside cellForRowAtIndexPath set itself as the delegate:

// inside cellForRowAtIndexPath:
cell.stepperCellDelegate = self

Upvotes: 2

smaura777
smaura777

Reputation: 326

Delegation is the proper way of handling this.

That UItableviewCell — both appear to be similar — should expose a protocol with a set of methods that the UIViewController can implement. Methods are triggered when you tap on the UIStepper widget.

Best to stick to this methodology, and reuse it everywhere. Makes things manageable loosely coupled.

Upvotes: 1

Related Questions