My goal is to set off an animation when my second viewController is loaded. How do call the function once the view is loaded?
Here is the code:
UIView.animate(withDuration: 1.5, animations: {self.greyScreen.frame.origin.y = -0.39*self.screenHeight}, completion: nil)
Any advice much appreciated!
viewDidAppear() is the method of UIViewContoller Life Cycle which is called once the screen is completely visible i.e. loaded all views into the memory hierarchy. So put your this block of animation into this method. You'll get your animation effect
Place that code inside viewDidAppear.
viewDidAppear is called when the view is shown on the device, so adding that code to this method will trigger the animation as soon as the view is displayed.
Related
I am animating a view gradientView in/out using the following:
func hideOrShowGradientView(hide: Bool) {
UIView.animate(withDuration: 0.4, animations: {
self.gradientView.isHidden = hide
})
}
This works well, but on the first time, there is no animation. It just appears. On the second and third time it works wonderfully. I've tried calling the animate block on the main thread but no luck there. Why is this animation failing to occur on the first and only first time around? Should I be using another animation method?
Have you tried calling self.view.layoutIfNeeded(). It forces the view and it's subviews to complete any of it's pending animations immediately, which might be interfering with your animation. You can use it like this:
func hideOrShowGradientView(hide: Bool) {
self.view.layoutIfNeeded()
UIView.animate(withDuration: 0.4, animations: {
self.gradientView.isHidden = hide
self.view.layoutIfNeeded()
})
}
Apple recommends calling layoutIfNeeded() twice, once before the animation block which forces a redraw on the view and it's subviews, and it completes any pending animations on the view without waiting for the next update cycle, and call it the second time inside the animation block to make sure that the animation changes will be applied immediately.
I had too much going on the main thread in the init method, which was being called only on the first time the view was being presented. Moved unnecessary initialization into view did appear
I'm trying to develop Container View Controller as it is shown in Apple documentation.
For now I have simple init code in viewDidAppear:
presentedVC = self.storyboard!.instantiateViewControllerWithIdentifier(Storyboard.yesNoControllerID)
self.addChildViewController(presentedVC)
presentedID = Storyboard.yesNoControllerID
presentedVC.view.frame = containerView.bounds
self.containerView.addSubview(presentedVC.view)
presentedVC.didMoveToParentViewController(self)
I have implemented exchange method, like in Apple doc:
private func exchangeVC(withVC viewController: UIViewController){
presentedVC.willMoveToParentViewController(nil)
self.addChildViewController(viewController)
viewController.view.frame = newViewStartFrame
let endFrame = oldViewEndFrame
self.containerView.addSubview(viewController.view)
self.transitionFromViewController(presentedVC, toViewController: viewController, duration: 0.25, options: UIViewAnimationOptions.CurveLinear, animations: {
viewController.view.frame = self.presentedVC.view.frame
self.presentedVC.view.frame = endFrame
}) { (finished) in
self.presentedVC.view.removeFromSuperview()
self.presentedVC.removeFromParentViewController()
viewController.didMoveToParentViewController(self)
self.presentedVC = viewController
}
}
Then, I have button that is calling simply:
let controller = self.storyboard!.instantiateViewControllerWithIdentifier(presentedID)
exchangeVC(withVC: controller)
With this code, my controllers are animating on screen on button press. But at the end of animation I'm getting:
Unbalanced calls to begin/end appearance transitions for
UIViewController: 0x7aecf730.
Can You tell me what I have done wrong? How to get rid of this error/warning?
This is an easy mistake to make, but Apple's documentation for transition(from:to:duration:options:animations:completion:) states that:
This method adds the second view controller's view to the view
hierarchy and then performs the animations defined in your animations
block. After the animation completes, it removes the first view
controller's view from the view hierarchy.
You were getting that Unbalanced calls to begin/end appearance transitions warning because you were adding the subview once with:
self.containerView.addSubview(viewController.view)
... then adding it again when calling transition(from:to:duration:options:animations:completion:)
Removing the call to addSubview would fix the problem.
I had a similar issue. Generally, that warning appears when you try to present the same view controller without dismissing it first, but the transition method should handle all that for you. I ended up fixing it by using
UIView.animate(withDuration:animations:completion:)
instead of
UIViewController.transition(from:to:duration:options:animations:completion:)
as you are above. Of course, I had to manually add and remove the subviews as well. I'm not sure why this change worked, but my best guess is that there's something wrong with the UIViewController transition method that issues that warning. Fortunately the fix is really easy.
I was seeing this unbalanced calls error on iPhones, in button tap handler. traced it to a dismiss(animated: no) followed by a present(.. animated: no)
solution was to do the present in a completion handler for the dismiss call.
I have 2 view A and B.
At view A
presentViewController(viewB, animation: true) {
NSNotificationCenter.defautCenter.postNotificationName("addButton")
}
At view B:
var masterView:UIView!
func addButton(notification: NSNotification){
var button:UIButton!
button.frame = masterView.caculator // set frame for button
self.addSubview(button)
}
When view B finished animation on simulator( go from Bottom). Button added after delay 0.3s.
Following some document, when animation finish, method viewDidAppear called. i tried this way. But as I saw, button added after animation finish 0.3s
How to addButton immediately when animation finish?
Thank you!
I have solved it. Because in viewDidAppear, this method was called when all Layout is loaded.
So we need implement add my button in LayoutSubview Method.
So, I want to do some basic animations of labels and later views.
I have a label, I'm trying to get it to move when a view loads, so I call the following method at the end of viewDidLoad:
- (void)animateView {
NSLog(#"animateView");
[UIView animateWithDuration:20 animations:^{
// set new position of label which it will animate to
self.dcFirstRunDaysLabel.frame = CGRectMake(20,320,280,215);
}];
}
Instead of animating, the label appears in position.
I've tried every tutorial and read through the docs. I get no errors.
Any thoughts?
Cheers.
Try calling your animateView method in viewDidAppear. Because in viewDidLoad your view isn't visible yet.
viewDidLoad:
Called after the controller’s view is loaded into memory.
viewDidAppear:
Notifies the view controller that its view was added to a view hierarchy.
I have a repeating timer that belongs to a UIView subclass.
The class has a nib that loads it and I'm using ARC.
I'd like to invalidate the timer when the UIView is either...
Removed from its superview
The ViewController that contains its superView is popped off the stack.
I can't seem to find a method like viewDidDisappear on UIView.
Is there any other way to intercept this?
At the moment, after the ViewController is popped the timer keeps firing and creating NSLog outputs.
For the view controller being popped: just use viewDidDisappear or similar. There's also UINavigationControllerDelegate that may be useful.
For the view itself: have you tried using willMoveToSuperview: method in UIView? I haven't verified this, but in theory the view will move to superview nil when it is removed from its superview.
So try the following in your view:
- (void)willMoveToSuperview:(UIView *)superview {
if (!superview) {
// cancel timers
}
}
There's also a willRemoveSubview: method, but that would get called on the superview rather than the view being removed.
Have you tried invalidating it in the dealloc