0

I have a problem where elements are not being added to my TableView-array.

My set up is quite complex..

I have a popUpView and in there is a dropDownButton with a dropDownTableView.

Here is my "DropDown.file" :

    class dropDownView: UIView, UITableViewDelegate, UITableViewDataSource  {

    var dropDownOptions = [String]()

    var tableView = UITableView()

    var delegate : dropDownProtocol!

    override init(frame: CGRect) {
        super.init(frame: frame)

        tableView.backgroundColor = UIColor.darkGray
        self.backgroundColor = UIColor.darkGray


        tableView.delegate = self
        tableView.dataSource = self

        tableView.translatesAutoresizingMaskIntoConstraints = false

        self.addSubview(tableView)

        tableView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        tableView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
        tableView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

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

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dropDownOptions.count
    }

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

        cell.textLabel?.text = dropDownOptions[indexPath.row]
        cell.backgroundColor = UIColor.lightGray
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.delegate.dropDownPressed(string: dropDownOptions[indexPath.row])
        self.tableView.deselectRow(at: indexPath, animated: true)
    }

}


protocol dropDownProtocol {
    func dropDownPressed(string : String)
}

//MARK: DropDownButton

class dropDownBtn: UIButton, dropDownProtocol {

    func dropDownPressed(string: String) {
        self.setTitle(string, for: .normal)
        self.dismissDropDown()
    }

    var dropView = dropDownView()

    var height = NSLayoutConstraint()


    override init(frame: CGRect) {
        super.init(frame: frame)

        self.backgroundColor = UIColor.lightGray

        dropView = dropDownView.init(frame: CGRect.init(x: 0, y: 0, width: 0, height: 0))
        dropView.delegate = self
        dropView.translatesAutoresizingMaskIntoConstraints = false
    }

    override func didMoveToSuperview() {
        self.superview?.addSubview(dropView)
        self.superview?.bringSubviewToFront(dropView)
        dropView.topAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        dropView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
        dropView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
        height = dropView.heightAnchor.constraint(equalToConstant: 0)
    }

    var isOpen = false
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if isOpen == false {

            isOpen = true

            NSLayoutConstraint.deactivate([self.height])

            if self.dropView.tableView.contentSize.height > 150 {
                self.height.constant = 150
            } else {
                self.height.constant = self.dropView.tableView.contentSize.height
            }


            NSLayoutConstraint.activate([self.height])

            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
                self.dropView.layoutIfNeeded()
                self.dropView.center.y += self.dropView.frame.height / 2
            }, completion: nil)

        } else {
            isOpen = false

            NSLayoutConstraint.deactivate([self.height])
            self.height.constant = 0
            NSLayoutConstraint.activate([self.height])
            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
                self.dropView.center.y -= self.dropView.frame.height / 2
                self.dropView.layoutIfNeeded()
            }, completion: nil)

        }
    }

    func dismissDropDown() {
        isOpen = false
        NSLayoutConstraint.deactivate([self.height])
        self.height.constant = 0
        NSLayoutConstraint.activate([self.height])
        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
            self.dropView.center.y -= self.dropView.frame.height / 2
            self.dropView.layoutIfNeeded()
        }, completion: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

So what I do is I create the dropDownButton inside my ViewController and constrain it if the popUpView appears like this and also add the first element:

// constrain dropDownbutton
    dropDownButton.centerXAnchor.constraint(equalTo: self.popUpView.centerXAnchor).isActive = true
    dropDownButton.centerYAnchor.constraint(equalTo: self.popUpView.centerYAnchor).isActive = true
    dropDownButton.widthAnchor.constraint(equalToConstant: 170).isActive = true
    dropDownButton.heightAnchor.constraint(equalToConstant: 40).isActive = true

    //Set the drop down menu's options
    dropDownButton.dropView.dropDownOptions.append("Main Wishlist")

So far so good, that is working just fine. My problem is that I would like to be able to add elements to dropView.dropDownOptions from another func. Right now if I add an element from the other function it only adds the elements to the array until I let the popUpView appear for the first time. As soon as I let it appear and disappear again and try to add another element again it is not working and it just shows the old array without the new added element.

I tried to explain it as easy as possible. If anything is unclear just let me know and I will try to elaborate on that :)

2
  • 1
    You need to reload the data of tableview after appending elements to array. Commented Dec 15, 2019 at 4:33
  • that was it thanks :) Commented Dec 15, 2019 at 13:49

1 Answer 1

1

The simple approach is reload the table view from the main thread whenever new data appended to the array.

So, in your case, you can simply add a public method in dropDownView class to append the data. here's the example:

func append(data: String) {
   dropDownOptions.append(data)

   DispatchQueue.async.main { [weak self] in 
     self?.tableView.reloadData()
   }
}
Sign up to request clarification or add additional context in comments.

1 Comment

thanks for you answer, I did not even need an extra method. I just reload the tableView after appending like @Nexus suggested :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.