Chace
Chace

Reputation: 561

How to use UITableViews to create static and dynamic rows with Swift

This question follows up from this: Use UICollectionViews to create dynamic and multiple features.

I am able to create a static cell which displays the name and image of the recipe similar like this app:

enter image description here

Where I am stuck is creating a dynamic row which changes based on the amount of data inside i.e. utensils or nutritional values like the image below:

enter image description here

I know how to display rows of data on tableView normally. But not sure how to embed it into a section inside a tableView. I attempted to add multiple prototype cells and assign them to a subclass of UITableViewCell's. Then I try to use if statements in my cellForRow but this isn't soling my issue.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if indexPath.row == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FirstCell
        //set the data here

        cell.recipeTitle.text = recipe.name
        cell.imageView.image = UIImage(named: "url")
        return cell
    }
    else if indexPath.row == 1 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as! SecondCell
        //set the data here
        return cell
    }
    else {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell3", for: indexPath) as! ThirdCell
        //set the data here
        return cell
    }
}

I have also looked at this demonstration: https://medium.com/ios-os-x-development/ios-how-to-build-a-table-view-with-multiple-cell-types-2df91a206429, which is near to what I want to achieve but I have found it quite difficult to adapt to it.

If someone could direct me on how best to approach this or a good example then I would really appreciate it.

Upvotes: 0

Views: 2185

Answers (1)

returnVoid
returnVoid

Reputation: 644

First you can't have static cells and dynamic cells in the same tableView. So how do you work around that? Define each of the static cells in the sections they belong in as well as the dynamic cells in the sections they belong to. That, however doesn't look like what you are trying to do. You just want multiple sections in the same tableView, each section with a different list of data

To do this you will need the number of sections so use the tableView(_:numberOfSections:) function.

override func numberOfSections(in tableView: UITableView) -> Int {
    return 3
}

You can then(and probably should) give each of those sections a title by initializing an array with the titles in your tableViewController(assuming thats what you are using. It could also just be a tableView).

let headerTitles = ["Nutritional Values", "Utensils", "Ingredients"]

Then use the tableView(_:titleForHeaderInSection:)

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    if section < headerTitles.count {
        return headerTitles[section]
    }
    return nil
}

Now you can start defining your rows by the sections.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: UITableViewCell

    if indexPath.section == 0 {
        //Setup up the first row
        if indexPath.row == 0 {
            //I'm not sure where or how you defined First/SecondCell but this may not work depending on those two questions.
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FirstCell                
            return cell
        } else if indexPath.row == 1 {
            let cell = Bundle.main.loadNibNamed("StaticCell", owner: self, options: nil)?.first as! StaticCell
            return cell
        }

    } else if indexPath.section == 1 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! SecondCell  
        //setup cell1 n your storyboard to have a label with a tag # of 12(or whatever number you want to use)
        //you also want an array with your utensil data accessible here
        let label = cell.viewWithTag(12) as! UILabel
        label.text = utensilNames[indexPath.row]              
            return cell

    } else if indexPath.section == 2 {
        let cellIngredients = tableView.dequeueReusableCell(withIdentifier: "Ingredients", for: indexPath)

        tableView.deselectRow(at: indexPath, animated: true)
        return cellIngreidents
    }
    cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
    return cell
}

The point here is to use sections then rows to distribute your data.

Just to clarify Section 0 Row 0 - N would be where you're static rows are setup. I found it best to use XIB files subclassing TableViewCell. Hope this helps.

EDIT So the way I'm looking at the "static" cells is in the first section the xib is the only put exactly where you tell it to be placed. In the example above the first section in the second cell is the

Upvotes: 1

Related Questions