Reputation: 198
I'm not very experienced in Swift. I have a tableView and custom cells in it, where are several labels, UISlider and UISwitch.
When i change slider values and hit submit(bar button item), I want to collect UISlider and UISwitch values from all cells.
What i tried:
1.Tags: I reached some cells, but stopped and could not reach currently invisible cells, and finally read some opinions, that tags are unlikely to use.
Question: Are there any clear pro et contra?
2.CellForRowAtIndexPath:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell") as! CustomTableViewCell
cell.Label1.text = "Long Tongue, size \(indexPath.row) cm"
cell.Label2.text = "Big Banana, size \(indexPath.row) inches"
return cell
}
@IBAction func submitTapped(sender: AnyObject) {
let cell = tableView(self.tableView , cellForRowAtIndexPath: NSIndexPath(forRow: 1, inSection: 0)) as! CustomTableViewCell
print(cell.Label1.text) // gives me
print(cell.Label2.text) // values
print(cell.customSlider.value) // gives me the value stated as
print(cell.customSwitch.on) // default
}
Do i understand correctly, that i call cellForRowAtIndexPath here and no wonder i get new instance of Custom Cell (processed by function)?
3."Wag the dog"
Unfortunately i've lost a SO link to discussion of this solution :(
I tried to reach UIViewController using .superview.superview..., but Xcode refused to eat 4 superviews (and i was not sure that i found correct number of .superviews).
Main idea is to give access to UIViewController property in Custom Cell:
add a property in CustomTableViewCell:
class CustomTableViewCell: UITableViewCell {
var viewController : MyViewController?
var cellNo = 0
//and so on
}
class MyViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var sliderValues: [Float] = []
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell") as! CustomTableViewCell
cell.Label1.text = "Long Tongue, size \(indexPath.row) cm"
cell.Label2.text = "Big Banana, size \(indexPath.row) inches"
self.sliderValues.append (0.0) // just to be sure that each slider can put it's value to Array
cell.cellNo = indexPath.row // so the Custom Cell knows it's No
//---------------------//
cell.viewController = self
//---------------------//
return cell
}
}
//----------------------
//and back to Custom Cell
@IBAction func sliderValueChanged(sender: AnyObject) {
self.viewController?.sliderValues[self.cellNo] = self.customSlider.value
}
// and the same way with UISwitch
Good News, This works!
Question: are there any methods not to "wag the dog" and reach Custom Cell from UIViewController?
Upvotes: 0
Views: 824
Reputation: 5275
Looking at your solution I think you will have an issue because the cell is holding onto a reference to your viewController, so it will lead to memory leaks. You should use "weak var viewController : MyViewController?" if you were going to go down this route
However, as matt has said, you should not do this. It is better to update your model with this data. You might be able to pass the data directly to the cell to modify the data, but I do not know the format of your data, so another idea is you could create a delegate to pass the values back from the cell. An example is:
protocol CustomTableViewCellDelegate: class {
func didChangeSlider(value: Float, cellNo: Int)
//func didSwitchOn(value: Bool, cellNo: Int)
}
You would then add this to your cell, like this:
class CustomTableViewCell: UITableViewCell {
weak var delegate: CustomTableViewCellDelegate?
var cellNo = 0
//and so on
}
Then use the delegate here:
@IBAction func sliderValueChanged(sender: AnyObject) {
self.delegate?.didChangeSlider(self.customSlider.value, cellNo)
}
Finally in your ViewController when you create the cell, you need to do this:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell") as! CustomTableViewCell
cell.Label1.text = "Long Tongue, size \(indexPath.row) cm"
cell.Label2.text = "Big Banana, size \(indexPath.row) inches"
cell.delegate = self
cell.cellNo = indexPath.row
return cell
}
Add at the end of your ViewController, add the delegate handler:
extension MyViewController: CustomTableViewCellDelegate {
func didChangeSlider(value: Float, cellNo: Int) {
//Save your value here
}
}
Upvotes: 1