Adding a programmatic UITabBarController and working with UIKit Animations.
class AnimationsTabController: UITabBarController {
private lazy var sampleAnimationsVC: SampleAnimationController = {
let viewcontroller = SampleAnimationController()
viewcontroller.tabBarItem = UITabBarItem(title: "Sample Animations", image: UIImage(systemName: "1.circle"), tag: 0)
return viewcontroller
}()
private lazy var constraintsAnimationVC: ConstraintsAnimationController = {
// ConstraintsAnimationController instance from storyboard
// step 1: get instance of storboard
let constraintsAnimationStoryboard = UIStoryboard(name: "ConstraintsAnimation", bundle: nil)
// step 2: instantiate view controller from storyboard instance
guard let viewcontroller = constraintsAnimationStoryboard.instantiateViewController(identifier: "ConstraintsAnimationController") as? ConstraintsAnimationController else {
fatalError("could not load ConstraintsAnimationController")
}
viewcontroller.tabBarItem = UITabBarItem(title: "Constraints Animation", image: UIImage(systemName: "2.circle"), tag: 1)
return viewcontroller
}()
override func viewDidLoad() {
super.viewDidLoad()
// set viewcontrollers for the tab bar
// in our app we will have two tabs
viewControllers = [sampleAnimationsVC, constraintsAnimationVC]
}
}Setting a UITabBarController as the root view controller for an app programmatically in the SceneDelegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: UIScreen.main.bounds)
window?.windowScene = windowScene
window?.rootViewController = AnimationsTabController()
window?.makeKeyAndVisible()
}- frame
- bounds
- center
- transform
- alpha
- backgroundColor
- contentStretch
CALayer animatable properties
- anchorPoint
- backgroundColor
- backgroundColorFilters
- borderColor
- borderWidth
- bounds
- compositingFilter
- contents
- contentRect
- cornerRadius
- doubleSided
- filters
- hidden
- mask
- maskToBounds
- opacity
- position
- shadowColor
- shadowOffset
- shadowPath
- shadowRadius
- sublayers
- sublayerTransform
- transform
- zPosition
UIView.animate(withDuration: 1.0, delay: 0.0, options: [], animations: {
self.sampleAnimationsView.pursuitLogo.transform = CGAffineTransform(scaleX: 20.0, y: 20.0)
self.sampleAnimationsView.pursuitLogo.alpha = 0.0
}) { (done) in
// gets called after initial animation is done
UIView.animate(withDuration: 0.5) {
self.sampleAnimationsView.swiftLogo.isHidden = false
self.sampleAnimationsView.swiftLogo.layer.cornerRadius = self.sampleAnimationsView.swiftLogo.bounds.size.width / 2.0
}
}@IBOutlet weak var viewYConstraint: NSLayoutConstraint!When we change the constraints in iOS and we need this change to be animated we only need to animate self.view.layoutIfNeeded and the animation will take place
layoutIfNeeded will get called as the view is marked "dirty" by iOS when a constraint change is detected
UIView.animate(withDuration: 1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 10.0, options: [.curveEaseIn], animations: {
self.view.layoutIfNeeded()
}, completion: nil)
