M
M
MarsFM2019-01-14 13:55:00
Swift
MarsFM, 2019-01-14 13:55:00

Why is view's redrawn to cell?

Plz tell me why my three views are redrawn (when I scroll or rotate the screen), which are in a custom stackView, but the data does not change?
(images at bottom)
ViewController:

let cells: [String] = ["StepCell", "GoalCell"]
var steps: [Step] = [] {
        didSet {
            tableView.reloadData()
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        spinner.startAnimating()
        
        Network.shared.loadDataUser { (response) in
            switch response {
            case .success(let steps):
                DispatchQueue.main.async {
                    self.steps = steps
                    self.spinner.stopAnimating()
                }
            case .refuse(let error):
                print(error)
            }
        }
    }

extension StepViewController: UITableViewDataSource {
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return steps.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return cells.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cellIdentifier = cells[indexPath.row]
        let step = steps[indexPath.section]
        
        switch cellIdentifier {
        case "StepCell":
            let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! StepTableViewCell
            cell.configure(step)
            return cell
        case "GoalCell":
            let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! GoalTableViewCell
            return cell
        default:
            let cell = UITableViewCell()
            return cell
        }
    }

}

StepTableViewCell:
@IBOutlet weak var customStackView: CustomStackView!
    
    var width: Int = 0
    
    func configure(_ step: Step) {
        dateLabel.text = getStringDate(for: step)
        myStepLabel.text = "\(step.getAllStep())"
        
        walkLabel.text = step.walk.description
        aerobicLabel.text = step.aerobic.description
        runLabel.text = step.run.description
    
        let allStep = step.getAllStep()
        let walk = getProportion(for: step.walk, allStep: allStep)
        let aerobic = getProportion(for: step.aerobic, allStep: allStep)
        let run  = getProportion(for: step.run, allStep: allStep)
        
        customStackView.setValues(walk, aerobic, run)
    }
    
    private func getStringDate(for step: Step) -> String {
        let formatter = DateFormatter.ddMMyyyy
        return formatter.string(from: step.date)
    }
    
    private func getProportion(for value: Int, allStep: Int) -> Double {
        return 100.0 * Double(value) / Double(allStep)
    }

CustomStackView:
required init(coder: NSCoder) {
        super.init(coder: coder)
        
        distribution = .fillProportionally
        axis = .horizontal
        spacing = 5.0
        
        addArrangedSubview(walk)
        addArrangedSubview(aerobic)
        addArrangedSubview(run)
    }
    
    func setValues(_ walk: Double, _ aerobic: Double, _ run: Double) {
        self.walk.proportion = walk
        self.aerobic.proportion = aerobic
        self.run.proportion = run
    }

CustomProgressBar:
class CustomProgressBar: UIView {
    
    var proportion = 1.0
    
    override var intrinsicContentSize: CGSize {
        return CGSize(width: proportion, height: 1.0)
    }

}

5c3c65e642a18338084766.png5c3c6920659e2334904264.png

Answer the question

In order to leave comments, you need to log in

2 answer(s)
D
doublench21, 2019-01-14
@doublench21

class CustomProgressBar: UIView {
    
    var proportion = 1.0 { 
      didSet { invalidateIntrinsicContentSize() }
    }

    
    override var intrinsicContentSize: CGSize {
        return CGSize(width: proportion, height: 1.0)
    }

}

B
briahas, 2019-01-24
@briahas

Show what you have in cell.configure(step)
"Tormented" your code a bit. Mdaaa ... a very interesting situation has emerged. Failed for two hours.
It turns out that even if you remove progressbars from the stackview and then add them, their size still does not change.
But, this is exactly the solution I found - to remove everything from the stackview. It's just that I added in the wrong place.
Briefly speaking. Your code is good, just add

arrangedSubviews.forEach { $0.removeFromSuperview() }
the first line in your method setValues
thought about it this morning, and realized that it's better that the logic is in one method, and not scattered over several, so I would do this:
- removed from CustomStackView override func layoutSubviews()
- rewritten setValuesas follows:
func setValues(_ walkValue: Double, _ aerobicValue: Double, _ runValue: Double) {
        
        arrangedSubviews.forEach { $0.removeFromSuperview() }
        
        setNeedsLayout()
        layoutIfNeeded()
        
        walk.proportion = walkValue
        aerobic.proportion = aerobicValue
        run.proportion = runValue

        addArrangedSubview(walk)
        addArrangedSubview(aerobic)
        addArrangedSubview(run)
    }

... works for me.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question