My Custom UIView is not removed from SuperView

Viewed 870

I have one PopUpView which I add to a ViewController.

I have created a delegate Method didTapOnOKPopUp() so that when I click on Ok Button in the PopUpView, It should remove from the ViewController which using it's delegate.

Here is the code for PopUpView.Swift

protocol PopUpViewDelegate: class {
    func didTapOnOKPopUp()
}


class PopUpView: UIView {
weak var delegate : PopUpViewDelegate?

@IBAction func btnOkPopUpTap(_ sender: UIButton)
    {
        delegate?.didTapOnOKPopUp()
    }
}

Here is the code for ForgotPasswordViewController where I am using delegate method.

class ForgotPasswordViewController: UIViewController, PopUpViewDelegate {

// I have created an Instance for the PopUpView and assign Delegate also.

func popUpInstance() -> UIView {
        let popUpView = UINib(nibName: "PopUpView", bundle: nil).instantiate(withOwner: nil, options: nil).first as! PopUpView
        popUpView.delegate = self
        return popUpView
    }
// Here I am adding my view as Subview. It's added successfully.
@IBAction func btnSendTap(_ sender: UIButton) {
        self.view.addSubview(self.popUpInstance())
    }

It's added successfully

// But when I tapping on OK Button. My PopUpView is not removing from it's View Controller. 

func didTapOnOKPopUp() {

        self.popUpInstance().removeFromSuperview()
    }
}

I have tried this but No Success! Please Help me. Thanks!

3 Answers

Each call to popupinstance() creates a new PopUp View.

You can either create a reference to the created pop up :

private var displayedPopUp: UIView?
@IBAction func btnSendTap(_ sender: UIButton) {
    displayedPopUp = self.popUpInstance()
    self.view.addSubview(displayedPopUp)
}


func didTapOnOKPopUp() {
    self.displayedPopUp?.removeFromSuperview()
    displayedPopUp = nil
}

But I think in your case using a lazy var is better :

replace

func popUpInstance() -> UIView {
        let popUpView = UINib(nibName: "PopUpView", bundle: nil).instantiate(withOwner: nil, options: nil).first as! PopUpView
        popUpView.delegate = self
        return popUpView
    }

by :

lazy var popUpInstance : UIView =  {
        let popUpView = UINib(nibName: "PopUpView", bundle: nil).instantiate(withOwner: nil, options: nil).first as! PopUpView
        popUpView.delegate = self
        return popUpView
    }()

Now every call to popUpInstance will return the same instance of your popUp

Every time you call .popUpInstance(), it creates a brand new PopupView instance, thus causing you to lose the reference to the previously created and added one in the view hierarchy.

Define popUpView as an instance variable and you should be good to go:

class ForgotPasswordViewController: UIViewController, PopUpViewDelegate {

  private lazy var popupView: PopUpView = {
    let popUpView = UINib(nibName: "PopUpView", bundle: nil)
      .instantiate(withOwner: nil, options: nil)
      .first as! PopUpView

     popUpView.delegate = self
     return popUpView
  }()

  @IBAction func btnSendTap(_ sender: UIButton) {
    self.view.addSubview(self.popupView)
  }

  func didTapOnOKPopUp() {
    self.popupView.removeFromSuperview()
  }
}

Every time you call the function popUpInstance you create another instance of PopUpView, when you do so your delegate is not relevant.

you can do this part of the code in some ways:

  1. create the popUpInstance() function and save the instance as a class parameter

  2. make a class parameter like this

    private lazy var popupView: PopUpView = {
        let popUpView = UINib(nibName: "PopUpView", bundle: nil).instantiate(withOwner: nil, options: nil).first as! PopUpView
        popUpView.delegate = self
        return popUpView 
    }()
    
Related