You are using a UIStackView
in the wrong way. Stack views will arrange the subviews for you - no need to be calculating widths and setting frames.
Layout your cell prototype like this:

Note that the Bottom constraint has Priority: 999
. Auto-layout needs to make multiple "passes" to lay out stack views (particularly in table view cells). Using a priority of 999 for the bottom constraint will avoid Constraint Conflict error / warning messages.
Set the stack view properties like this:

With Distribution: Fill Equally
we don't have to do any let size = self.bounds.width / CGFloat(pictograms.count + 1)
kind of calculations.
Also, to make design-time a little easier, give the stack view a Placeholder
intrinsic height:

That will have no effect at run-time, but allows you to clearly see your cell elements at design time.
Now, when you "fill" the stack view with image views, no .frame =
setting, and the only constraint you need to add is Height == Width:
NSLayoutConstraint.activate([
// image view should have 1:1 ratio
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor),
])
Here is a complete example:
class HorizontalImagesStackCell: UITableViewCell {
@IBOutlet var theStack: UIStackView!
func addImages(_ pictograms: [String]) -> Void {
// cells are reused, so remove any previously added image views
theStack.arrangedSubviews.forEach {
$0.removeFromSuperview()
}
pictograms.forEach { s in
// make sure we can load the image
if let img = UIImage(named: s) {
// instantiate an image view
let imageView = UIImageView()
// give it a background color so we can see its frame
imageView.backgroundColor = .green
// scale aspect fit
imageView.contentMode = .scaleAspectFit
// set the image
imageView.image = img
NSLayoutConstraint.activate([
// image view should have 1:1 ratio
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor),
])
// add it to the stack
theStack.addArrangedSubview(imageView)
}
}
}
}
class ImagesInStackTableViewController: UITableViewController {
// we'll display 5 rows of images
// going from 5 images to 4 images ... to 1 image
let myData: [Int] = [5, 4, 3, 2, 1]
let myImages: [String] = [
"img1", "img2", "img3", "img4", "img5"
]
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HCell", for: indexPath) as! HorizontalImagesStackCell
// get the first n number of images
let a: [String] = Array(myImages.prefix(myData[indexPath.row]))
cell.addImages(a)
return cell
}
}
Using these 5 images:





We get this result (image views are set to .scaleAspectFit
and have green backgrounds so we can see the frames):
