AL3MS
AL3MS

Reputation: 91

How to use a string' value as an object name?

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

Answers (1)

jefflovejapan
jefflovejapan

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
  }
}

Update

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

Related Questions