Reputation: 91
I have many objects and I need to use one of them depending on whatever the user pressed to fill my table view. for reducing the use of if statements I think that maybe storing the name of the needed object on a string variable will help. and when the need of filling the table view the string variable will be used instead of check which the approbate object name.
// objects defined here from different classes.
var currentSection : String
@IBAction func button(_ sender: UIButton) {
if sender.tag == 1 { //
currentSection = "object1"
}
else if sender.tag == 2 { //
currentSection = "object2"
}
.........etc
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return(currentSection.item.count)
}
this is what I had done but it didn't work, error: "Value of type 'String' has no member 'item'"
anyone please telling me how to tell the compiler to use the string' value as an object name?
Upvotes: 0
Views: 527
Reputation: 2121
Since currentSection
is a string, it doesn't know anything about objects, so currentSection.item
is meaningless. Instead, what you could do is use a dictionary that associates string keys to values that represent the data in your section.
struct RowItem {} // the thing that represents the text for your table view row
class MyViewController {
var sectionData: [String: [RowItem]] = [:] // a dictionary that associates string keys to arrays of RowItem
var currentSection: String = ""
func tableView(_ tableView, numberOfRowsInSection section: Int) -> Int {
let thisSection = sectionData[currentSection] ?? [] // you might not have data in the dictionary for currentSection
return thisSection.count
}
}
What is the type that you are using to back your table view cells? In cellForRow
you have to configure a cell with some text, images, etc. — whatever the type is of the object that you're using for this (I used RowItem
above) should be the type in your dictionary -- [String: [MyRowTypeWhateverThatIs]]
. So each string key maps to a value that's an array of data. The items in this array will correspond to the cells in your table view.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let dataForKey: [RowItemOrWhatever] = sectionData[currentSection] ?? [] // this array contains items that correspond 1:1 to the cells in your table view
if indexPath.row >= dataForKey.count { return UITableViewCell() } // it's possible that this index could be outside the bounds of dataForKey, so we need to handle that case sensibly
let cell = tableView.dequeueReusableCell(withIdentifier: reusableCellIdentifier, for: indexPath)
let item = dataForKey[indexPath.row]
cell.textLabel?.text = item.text // or whatever it is that you're doing with these pieces of data
return cell
}
That way you can use the count of the array in numberOfRows
and index into the array to get the value for a specific row in cellForRow
. As far as IndexPath goes, you only want to use that to index into your own data in cellForRow -- you shouldn't need to store index paths. You will want to define RowItem
in such a way that it will have the data you need to configure your cell. So if my cell has some main text, some detail text, and an image, i would define RowItem
like this:
struct RowItem {
var mainText: String
var detailText: String
var image: UIImage
}
Upvotes: 1