2
votes

I have a custom UIView that I want to cover the screen once the user taps a button. It kind of simulates a custom view. There is child UIView in the custom UIView that should animate from the bottom (hidden at first) up to it's normal position (visible at the bottom). The problem that I am having is that it seems like layoutSubviews is a bad place to start doing animations. Where would the correct place be? Something like viewDidAppear but for UIViews.

In UIViewController:

let rect: CGRect = CGRectMake(0, 0, view.bounds.size.width, view.bounds.size.height)
let alertView = AlertView(frame: rect)
view.addSubview(alertView)

In the AlertView:

import UIKit

class AlertView: UIView {

let nibName = "AlertView"
let animationDuration = 0.5

var view: UIView!

@IBOutlet weak var notificationView: UIView!
@IBOutlet weak var notificationBottomConstraint: NSLayoutConstraint!

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

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

override func didAddSubview(subview: UIView) {
    super.didAddSubview(subview)
}

func viewSetup() {
    view = loadViewFromNib()
    view.frame = bounds
    view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]

    // move the notification view offscreen
    notificationBottomConstraint.constant = -notificationView.frame.size.height

    addSubview(view)
}

func loadViewFromNib() -> UIView {
    let bundle = NSBundle(forClass: self.dynamicType)
    let nib = UINib(nibName: nibName, bundle: bundle)

    return nib.instantiateWithOwner(self, options: nil)[0] as! UIView
}

override func layoutSubviews() {
    super.layoutSubviews()
    print("layoutSubviews")

    animate()
}

func animate() {
    // move the notification up 
    self.notificationBottomConstraint.constant = 0

    UIView.animateWithDuration(animationDuration) { () -> Void in
        self.view.setNeedsDisplay()
    }
}

}

2

2 Answers

3
votes

I suggest you to call your animate() function from one of these methods:

  • willMoveToSuperview:
  • didMoveToSuperview

These methods of UIView as needed to track the movement of the current view in your view hierarchy.

Reference: UIView class

0
votes

Your final constraint value is not in your animate closure. Try this:

func animate() {
    // move the notification up 
    UIView.animateWithDuration(animationDuration) { () -> Void in
        self.notificationBottomConstraint.constant = 0
        self.view.setNeedsDisplay()
    }
}