The removeFromSuperview() method is not animatable, what you can do is making alpha goes to 0 and after it has finished you can safely remove from super view.
If you want to get the same effect as in push, you just need to take your code and create the opposite transition. Since it seems that you are using view controllers you can take advantage of the transitions API.
func push(_ viewController: UIViewController, animated: Bool, completion: (()->())?) {
let oldVC = viewControllersStack.topItem()!
viewController.view.frame = oldVC.view.frame
self.addChildViewController(viewController)
oldVC.willMove(toParentViewController: nil)
let duration = animated ? Constants.GeneralValues.PopPushAnimationDuration : 0.0
transition(from: oldVC, to: viewController, duration: duration, options: [], animations: { () -> Void in
let animation = CATransition()
animation.duration = CFTimeInterval(duration)
animation.type = kCATransitionMoveIn
animation.timingFunction = CAMediaTimingFunction(name: "easeInEaseOut")
animation.subtype = "fromRight"
animation.fillMode = "forwards"
self.mainContainerView.layer.add(animation, forKey: "animoteKey")
// Constraint
guard let v = viewController.view else {
return
}
v.translatesAutoresizingMaskIntoConstraints = false
let hConstr = NSLayoutConstraint.constraints(withVisualFormat: "H:|[v]|", options:[], metrics:nil, views:["v":v])
let vConstr = NSLayoutConstraint.constraints(withVisualFormat: "V:|[v]|", options:[], metrics:nil, views:["v":v])
let constrs: [NSLayoutConstraint] = [hConstr, vConstr].flatMap {$0}
NSLayoutConstraint.activate(constrs)
}) { (finished) -> Void in
oldVC.removeFromParentViewController()
self.viewControllersStack.push(viewController)
viewController.didMove(toParentViewController: self)
if let completion = completion {
completion()
}
}
}
func popViewController(_ animated: Bool, completion: (()->())?) {
let oldVC = viewControllersStack.topItem()!
let viewController = viewControllersStack.penultimate!
viewController.view.frame = oldVC.view.frame
self.addChildViewController(viewController)
oldVC.willMove(toParentViewController: nil)
let duration = animated ? Constants.GeneralValues.PopPushAnimationDuration : 0.0
transition(from: oldVC, to: viewController, duration: duration, options: [], animations: { () -> Void in
let animation = CATransition()
animation.duration = CFTimeInterval(duration)
animation.type = kCATransitionReveal
animation.timingFunction = CAMediaTimingFunction(name: "easeInEaseOut")
animation.subtype = "fromLeft"
animation.fillMode = "forwards"
self.mainContainerView.layer.add(animation, forKey: "animoteKey")
// Constraint
guard let v = viewController.view else {
return
}
v.translatesAutoresizingMaskIntoConstraints = false
let hConstr = NSLayoutConstraint.constraints(withVisualFormat: "H:|[v]|", options:[], metrics:nil, views:["v":v])
let vConstr = NSLayoutConstraint.constraints(withVisualFormat: "V:|[v]|", options:[], metrics:nil, views:["v":v])
let constrs: [NSLayoutConstraint] = [hConstr, vConstr].flatMap {$0}
NSLayoutConstraint.activate(constrs)
}) { (finished) -> Void in
print("Fine")
oldVC.removeFromParentViewController()
_ = self.viewControllersStack.pop()
viewController.didMove(toParentViewController: self)
if let completion = completion {
completion()
}
}
}
This is a sort of implementation that I used to achieve the same you want but for pushing and popping view controllers in a container, but the animation is the same, just change constraints, to keep the sideview controller thin.