0

I am currently starting to learn how to build my own iOS Apps with Swift. My current project should help organize recipes. For this, the App displays a table with the some dishes (inside a Table View Controller at the start). Once the user clicks at a cell, the details of that dish (from my CoreDate) should be displayed inside a View Controller embedded inside a scroll view. So far so good... This is how my VieController for the clicked dish should look like:

Storyboard Image of my detail View

Inside this View Controller, I have a table with the ingredients needed for the dish. This table view should embed all the cells which describe the ingredients, as long as they together do not exceed a maximal height threshold of 300. In this case, all dishes are visible without scrolling. If a height of 300 is not enough to display all ingredients, the height of the table should be set to 300 and the user can scroll through the table of ingredients. So the height of the table depends on the size and content of the cells, which is why I can't just define it at the very start (at ViewDidLoad).

Now, when I click on the dish of my choice, the following screen appears:

Immediately after clicking dish

And after waiting maybe half a second, the view is updated appropriately:

Updated Screen

So the problem is: the label "Zubereitung" right under my table only appears with a certain delay. I imagine that might be because the screen loads and initially works with the initial value I set my table height to be inside the storyboard(being 300). So the label "Zubereitung" stays 300 under the table. Only when I adjust the height of the table (in this case to a value below 300) can my label take its desired place.

That's why I wanted to ask, how I could avoid this problem. Or if there is a smarter or better way to adjust the table size dynamically with the content of my table? Currently I do it by overwriting the height constraint inside the function ViewDidAppear.

The code of the ViewController representing the selected dish is the following:

import UIKit

class MyDishViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    
    @IBOutlet weak var nameOfDish: UILabel!
    @IBOutlet weak var imageOfDish: UIImageView!
    @IBOutlet weak var categoryOfDish: UILabel!
    @IBOutlet weak var complexityOfDish: UILabel!
    @IBOutlet weak var time: UILabel!
    
    @IBOutlet weak var ingredientTable: UITableView!
    
    @IBOutlet weak var tableIngredientHeight: NSLayoutConstraint!
    
    var dish : Dish? = nil

    override func viewDidLoad() {
        super.viewDidLoad()
        
        ingredientTable.delegate = self
        ingredientTable.dataSource = self
        
        ingredientTable.rowHeight = UITableView.automaticDimension
        ingredientTable.estimatedRowHeight = 60//0
        
        if let text = dish?.nameDish{
            nameOfDish.text = text
        }
        
        if let data = dish?.imageDish {
            imageOfDish.image = UIImage(data: data)
        }
        
        if let category = dish?.category{
            categoryOfDish.text = category
        }
        
        if let complexity = dish?.complexity{
            complexityOfDish.text = complexity
        }
    }
    
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let height = self.ingredientTable.contentSize.height
        if height > 300 {
            self.tableIngredientHeight.constant = 300
        }
        else{
            self.tableIngredientHeight.constant = height
        }
    }
    
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if let ingredients = dish?.ingredients{
            let lines = ingredients.split(whereSeparator: \.isNewline)
            return lines.count
        }
        else{
            return 0
        }
    }
    
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                
        let cell = tableView.dequeueReusableCell(withIdentifier: "ingredientCell", for: indexPath) as! listingTableViewCell
        
        if let ingredients = dish?.ingredients{
            let lines = ingredients.split(whereSeparator: \.isNewline)
            let item = lines[indexPath.row]
            cell.item?.text = String(item)
        }
        return cell
    }
}


Thank you very much!

Tori Mori
  • 3
  • 4
  • There is no need to set the content height directly if you properly constrain its subviews. I know you are using Interface Builder (which I'd recommend you not use because it's junk and slows down newbs tremendously) but refer to this link for the concept of how to configure auto layout with table and scroll views. https://stackoverflow.com/a/48219419/9086770 – trndjc Jun 19 '22 at 22:37
  • @fakegirlfriends Thank you very much for your answer, but I am not sure if I understand what you mean. I don't need to set the height constraint of the table in order for my view to work, I just needed it in order to have something in my ViewController to manipulate the height with. With the constraint all I could do is set the table's position relative to the other elements of my view, but this is already working. The only issue is how much the table should display without the need to scroll. I am not sure how to set this inside the Interface Builder. – Tori Mori Jun 19 '22 at 23:47

0 Answers0