Search code examples
swiftuinavigationcontrolleruilabel

Swift sub view hold old values (stacking new values on top of it)


[solved :) by adding self.progressScrollView?.removeFromSuperview() ]

I am new to swift. and having below issue :( please help me.

enter image description here

every time I come back to this main screen (using back button) my scroll view's content are showing new values on top of old values

for example.

I have 4 items(a,b,c,d) in an array. and main page show in random order

a
b
c
d

after that, i went to another page and came back to this screen.

it shows new values on top of old values

a -> b (this value is on top of 'a')
b -> d (this value is on top of 'b')
c -> c (this value is on top of 'c')
d -> a (this value is on top of 'd')

what I did?

  1. I re-initialize my array in viewdidappear()
  2. added below in gotopage() dismiss(animated: true, completion: nil)
  3. add removefromsuperview & view.addsubview in self.displayProgressBar() (what @sandeep suggested.. but doesn't work)

my flow:

1.call displayprogressbar in viewdidload self.displayProgressBar()


    class ViewController: UIViewController ,ChartViewDelegate, UIScrollViewDelegate {
...
    
    var progressScrollView: UIScrollView!
...
         override func viewDidLoad() {
                super.viewDidLoad()
             
                self.getfirebasedata() 
              
           

2.add progress bars and labels dynamically based on the list size.

     func getfirebasedata(...){ 
      ...
        self.displayProgressBar(...)
     }
    func displayProgressBar(...){     

            self.progressScrollView?.removeFromSuperview() //this is the fix
            self.progressScrollView = UIScrollView()
             
            self.progressScrollView.isScrollEnabled = true
            self.progressScrollView.frame = CGRect(x: 0, y: 300,
                                                                  width: self.view.frame.size.width, height: 200)
                self.progressScrollView.contentSize = CGSize(width: self.view.frame.size.width,
                                                                        height: self.view.frame.size.height)
            let axisXstartPoint = ( self.view.frame.size.width - 200 ) / 2
          
            let progressView = UIProgressView(progressViewStyle: .bar)
      ...
            
            let label = UILabel()
          
            label.frame = CGRect(x: axisXstartPoint, y: CGFloat(axisY-15), width: 200, height: 20)
            label.textAlignment = .left
            label.text = book.bookName
    
            label.isUserInteractionEnabled = true
            label.addGestureRecognizer(tapBookName)
            progressScrollView.addSubview(label)
            progressScrollView.addSubview(progressView)
           
            self.view.addSubview(progressScrollView)
            
        }
  1. when I go to another page I use this method
@objc @IBAction func goToAddPage(sender: UITapGestureRecognizer) {
        let label = sender.view as? UIButton
        let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let addViewController = storyBoard.instantiateViewController(withIdentifier: "add") as! AddViewController

        addViewController.modalPresentationStyle = .fullScreen
        self.navigationController?.pushViewController(addViewController, animated: true)
        dismiss(animated: true, completion: nil)
      }
         

4.this is my storyboard enter image description here


Solution

  • Not sure from where you call displayProgressBar as its not clear from your question, what you can do is add these statement as either 1st statment in displayProgressBar or as a statement before calling displayProgressBar

    Approach 1:

    self.progressScrollView?.removeFromSuperview() //? because for the first time implicit optional will be nil
    self.progressScrollView = UIScrollView()
    

    In ViewDidLoad you have self.view.removeFromSuperview() which I have no idea why? Makes no sense to me why would you try to remove ViewController's view? May be you were trying to remove subviews I assume, if yes, thats not the proper way to remove subviews, you iterate over subViews and call removeFromSuperview on each subView, but I dont think you need that, clearly from your code you hold a reference to progressScrollView somewhere in your code, just remove it from subview and recreate the progressScrollView as

    progressScrollView = UIScrollView()

    And if you are not holding a reference to progressScrollView and instead you were creating it as only local variable in displayProgressBar method, hold a reference to this view, to do that declare a instance variable var progressScrollView: UIScrollView!

    Approach 2:

    And if you dont prefer creating progressScrollView() again and again, you can always iterate over its subviews and remove them from superview one by one

            for view in progressScrollView.subviews {
                view.removeFromSuperview()
            }
    

    Make sure you run self.view.addSubview(progressScrollView) only once (like in ViewDidLoad or somewhere) if you decide to go with approach 2.

    In either case you need to hold a reference to progressScrollView