Referring to your answer -in the comments- about using constraints:
Yes, I do. I'm assuming this has something to do with it? Is the
constraints loaded after the viewDidLoad?
That's right, from viewDidLoad() documentation:
Called after the controller's view is loaded into memory.
Nothing to do with checking that the setup of constraints have been done (subviews laid out).
If I'm not mistaking, what are you looking for is the viewDidLayoutSubviews() method:
Called to notify the view controller that its view has just laid out
its subviews.
Your view controller can override this method to make changes after
the view lays out its subviews. The default implementation of this
method does nothing.
So, instead of implementing the code of changing the y position of the view in the viewDidLoad()
try to let it in the viewDidLayoutSubviews()
, as follows:
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let xPosition = dynView.frame.origin.x - 100
let yPosition = dynView.frame.origin.y
let height = dynView.frame.size.height
let width = dynView.frame.size.width
UIView.animate(withDuration: 1.0, animations: {
self.dynView.frame = CGRect(x: xPosition, y: yPosition, width: width, height: height)
})
}
ALSO:
If you don't want to let the animation to be repeated after popping/dismissing the next ViewController, you can declare a flag property for determining to start the animation or not, similar to:
var isAnimated = false
override func viewDidLayoutSubviews() {
if isAnimated == false {
super.viewDidLayoutSubviews()
UIView.animate(withDuration: 1.0, animations: {
self.btn.frame.origin.y = 20
}, completion: { _ in
self.isAnimated = true
})
}
}
Additional Note:
I recommend changing the value of constraints instead of directly change the frame size/origin. You might want to check this question/answer.