Search code examples
iosswiftuiviewautolayoutxib

XIB view not showing with correct layout [iOS Swift]


I'm trying to make a custom alert view and facing some issues with the fact that the displayed view is cutting the bottom half of the view (Images below)

How it's being displayed:

How it's being displayed

Desired Output:

Desired output

So basically, I have a XIB called CustomAlertView supported by a class of same name with init as follows:

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

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    commonInit()
}

private func commonInit() {
    Bundle.main.loadNibNamed("CustomAlertView", owner: self, options: nil)
    contentView.frame = self.bounds
    contentView.translatesAutoresizingMaskIntoConstraints = true
    addSubview(contentView)
    //contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

}

I have another class that is responsible for creating an alert, CustomAlert, using the customAlertView. This CustomAlert class is creating the backgroundView and dialogView( which I'm trying to add my customAlertView to it) with the following code:

func initialize(title:String, description:String){
    dialogView.clipsToBounds = true

    backgroundView.frame = frame
    backgroundView.backgroundColor = UIColor.black
    backgroundView.alpha = 0.6
    backgroundView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTappedOnBackgroundView)))
    addSubview(backgroundView)

    dialogView.frame.origin = CGPoint(x: 0, y: 0)
    dialogView.frame.size = CGSize(width: frame.width-32, height: frame.height/3)

    dialogView.backgroundColor = UIColor.white
    dialogView.layer.cornerRadius = 6

    let alertView = CustomAlertView.init(frame: self.bounds)
    alertView.titleLabel.text = title
    alertView.descriptionLabel.text = description
    alertView.cancelButton.backgroundColor = UIColor.brown

    dialogView.addSubview(alertView)


    addSubview(dialogView)
}

I believe that I'm making a confusion with the frames and bounds but couldn't find a solution.

I'd like the desired output to be placed perfectly inside the dialogView.

EDIT

Code for my .show function in CustomAlert

func show(animated:Bool){

    self.backgroundView.alpha = 0
    self.dialogView.center = CGPoint(x: self.center.x, y: self.frame.height + self.dialogView.frame.height/2)
    UIApplication.shared.delegate?.window??.rootViewController?.view.addSubview(self)
    if animated {
        UIView.animate(withDuration: 0.33, animations: {
            self.backgroundView.alpha = 0.66
        })
        UIView.animate(withDuration: 0.33, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 10, options: UIViewAnimationOptions(rawValue: 0), animations: {
            self.dialogView.center  = self.center
        }, completion: { (completed) in

        })
    }else{
        self.backgroundView.alpha = 0.66
        self.dialogView.center  = self.center
    }
}

Github link git-alert-view


Solution

  • For anyone facing the same difficulties as me, I was able to accomplish the wanted result.

    I used AutoLayouts as suggested by @HAK. But instead of writing my own NSLayoutConstraint I used roberthein library called TinyConstraints.

    Basically, I used as follow:

    Instead of

    NSLayoutConstraint.activate([
    alertView.topAnchor.constraint(equalTo: superview.topAnchor, constant: 0),
    alertView.leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: 0),
    alertView.bottomAnchor.constraint(equalTo: superview.bottomAnchor, constant: 0),
    alertView.trailingAnchor.constraint(equalTo: superview.trailingAnchor, constant: 
    0)])
    

    with TinyConstraints:

    alertView.edges(to: superview)
    

    That´s it