Waiting for a UIView to finish - objective-c

[_articleTxtView setFont:[UIFont systemFontOfSize:_fontSizeInt]];
[_articleTxtView layoutIfNeeded];
[_articleTxtView sizeToFit];
The above code is triggered with a press of a UIButton and responsible of changing the size of a UITextView. Every time the UIButton is pressed the _fontSizeInt changes to a bigger number and the UITextView height changes accordingly.
The problem is that layoutIfNeeded and sizeToFitare called before setFont is finished and cuts UITextView in the middle.
Possible solutions:
This solution works great but I'd preffer not using something with such a bad practice.
..
[_articleTxtView setFont:[UIFont systemFontOfSize:[DataManager sharedDataManager].fontSize]];
[self performSelector:#selector(test) withObject:nil afterDelay:0.01];
}
- (void)test
{
[_articleTxtView layoutIfNeeded];
[_articleTxtView sizeToFit];
}
I thought about using the next code but for some reason it doesn't always work. Also I'm not sure if that's a proper use of the animation block (there's really no animation involved):
[UIView animateWithDuration:0.4 animations:^()
{
[_articleTxtView setFont:[UIFont systemFontOfSize:[DataManager sharedDataManager].fontSize]];
}
completion:^(BOOL finished)
{
[_articleTxtView layoutIfNeeded];
[_articleTxtView sizeToFit];
}];
Is there a better way to let a method "know" when a UIView finished painting \ loading?
Thanks

You could implement viewDidLoad (called once) or viewWillAppear (called every time) in the articleTxtView view controller class

Related

Remove from superview not working in animation completion handler

I have a UIView with several UILabels added. I am simply moving them all to the center of the screen with an animation, and then attempting to remove them from their superview in the animation completion handler.
for (label in [self.view subviews])
{
if([label isKindOfClass:[UILabel class]])
{
CGRect frame = CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height/2, label.frame.size.width, label.frame.size.height);
[UIView animateWithDuration:2.0
delay:0.0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
[self->label setFrame:frame];
}
completion:^(BOOL finished){
dispatch_async(dispatch_get_main_queue(),^{
[self->label removeFromSuperview];
});
}
];
}
}
The problem that I am having is that at the end of the animation the UILabels remain. If I put the removeFromSuperView call outside of the animation block then it works, but of course then they are removed before the animation has a chance to complete.
You've got label as the variable in the for-in and self->label in the blocks. Apparently, you weren't operating on the label you thought you were.

UIView not animating constraint change

I have a question regarding the UIView method:
+ (void)animateWithDuration:(NSTimeInterval)duration
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion
Basically I am just trying to set a height constraints constant to 0 and have the change look like its slowly shrinking...
My Code looks like this:
[UIView animateWithDuration:0.7
animations:^{
//hide the Title
self.titleCellHeigthConstraint.constant = kLabelHeightZero;
[self.contentView layoutIfNeeded];
}
completion:nil];
Unfortunately it's not animating. It simply makes all changes appear with a little delay (which might be the 0.7 seconds specified in the method).
Now my question is if there is any way to get the UIView to animate the change?
Thanks in Advance!
Edit:
The weird thing is if I reverse the changes in an animated fashion it does it exactly the way I want it. The code I'am using for that is:
//animate layout changes
[UIView animateWithDuration:0.7
animations:^{
//hide activity indicator and label
[self.activityIndicator stopAnimating];
[self.label setHidden:YES];
}
completion:^(BOOL arg0){
[UIView animateWithDuration:0.3
animations:^{
//show title label
self.titleCellHeigthConstraint.constant = kDefaultLabelHeight;
[self.contentView layoutIfNeeded];
}];
}];
You want to change the properties of the UIView not the NSLayoutConstraint in the animation method. I.e. Change the layout constraint's constant before the UIView method and then change the UIView's frame property in the animation method.
This way you won't need to call layoutIfNeeded.

Alternative to "self" in calling methods in Objective-C

This may sound really noob, but i've spent an entire day wrestling with this problem and would appreciate some help.
You see i have a method which I call more than once inside gameplay. If I use [self myMethod]; then it works for ONE time. And then when I call it again, the animation in the method doesn't commence anymore.
What I need is to replace "self" with an alternative that can be "alloc'ed" and "released" to make my animations work.
I've tried;
#implementation gameViewController
gameViewController *object = [[gameViewController alloc] init];
[object myMethod];
However the above substitute for self doesn't even call on the method. I don't know what I did wrong, it's suppose to work just like "self".
Is there something i missed? How do you make an object of the class to work just like "self" does?
Thanks so much.
Here is a more detailed look of my code;
[self explosionAnimations];
- (void) explosionAnimations
{
UIImage *image = [UIImage imageNamed: #"Yellow Explosion.png"];
[bomb setImage:image];
[UIView beginAnimations:#"bomb1ExplosionIncrease" context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
bomb.transform = CGAffineTransformMakeScale(3.4, 3.4);
[UIView commitAnimations];
}
The setImage works fine every time. But the animations stop working on the second call of the method. While in the console it logs "animation completed" with nothing happening to the image.
This leads me to believe that somehow "self" believes that the animation was already done and will not bother to do it again. So I thought a new "alloc" might give it a kick awake.
The problem doesn't have anything to do with "self". The problem is that you set the transform in your animation, and then when you run it again, you're setting the same transform, so it does nothing. You need to reset the frame to the new frame and then set the transform back to the identity transform before you do the animation again. Also, you should be using block based animations. I'm not sure this is the best way to do it, but this worked for me (if you have auto layout turned off).
- (void)explosionAnimations {
UIImage *image = [UIImage imageNamed: #"Yellow Explosion.png"];
[self.bomb setImage:image];
[UIView animateWithDuration:.5 animations:^{
self.bomb.transform = CGAffineTransformMakeScale(3.4, 3.4);
} completion:^(BOOL finished) {
CGRect newFrame = self.bomb.frame;
self.bomb.transform = CGAffineTransformIdentity;
self.bomb.frame = newFrame;
}];
}
If you're doing this in an app with auto layout turned on (which it is by default), then I would not use a transform, but just resize the width and height of the image view by adjusting its height and width constraints. So, in this method, you should make IBOutlets to height and width constraints you make in IB, then change their constant values in an animation block:
[UIView animateWithDuration:.5 animations:^{
self.heightCon.constant = self.heightCon.constant * 3.4;
self.widthCon.constant = self.widthCon.constant * 3.4;
[self.view layoutIfNeeded];
}];

Simple UIView animation move doesn't work

I have no idea, why it is not working.
All I want to do is a simple UIView animation in the viewDidLoad.
Here's my code:
[UIView animateWithDuration:3.0f animations:^{
[self.headline setCenter:CGPointMake(0.0, 200.0)];
}];
Nothing happens. When I test the general approach of calling a animation method on that particular object like this:
[UIView animateWithDuration:3.0f animations:^{
[self.headline setAlpha:0.0];
}];
it works!!! Why am I not able to move the view across the screen? I am using latest Xcode 4.5.
Thanks for any advice!
UPDATE:
When I add a view manually in code it works. But for the UIViews I create as Outlets in the Interface Builder it doesn't work.
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 200.0, 100.0)];
testLabel.backgroundColor = [UIColor redColor];
[self.view addSubview:testLabel];
[UIView animateWithDuration:3.0 animations:^{
testLabel.center = CGPointMake(0.0, 200);
}];
So obviously I am doing something wrong in the .xib file
Dont do it in viewDidLoad. The view is not pressent at that time yet.
Try it in viewDidAppear.
Well, I think the reason for the missing animation was the fact that I called a different push navigation animation from the view controller that was pushing the actual view on screen:
- (IBAction)goForSelection:(id)sender
{
SelectionViewController *selectionViewController = [[SelectionViewController alloc] initWithNibName:#"SelectionViewController" bundle:nil];
//[self.navigationController pushViewController:selectionViewController animated:YES];
[UIView transitionWithView:self.navigationController.view duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
[self.navigationController pushViewController:selectionViewController animated:NO];
} completion:^(BOOL finished) {
[selectionViewController startIntroAnimation];
}];
}
First I checked what happens when I use the default navigation controller segue. And to my surprise the animation did start. Then I inserted the call to the [selectionViewController startIntroAnimation] to the completion block and this works as well.

presentModalViewController translucent with previous view in the background

Im trying to present a view translucently and that the previous view sticks around and be that its visible in the background.
I've got
[self presentModalViewController:modalView animation:YES];
and I have the transparency set in the modalView's viewDidLoad, but after modalView gets brought up the previous view disappears. What can I do to keep the other view to stay around in the background?
I have also tried adding it with
[self.view addSubview:modalView.view];
It doesn't cover the whole screen, I would like to be able to solve this problem using presentModalViewController method.
It sounds like you just want a view to be displayed on top of your main view. Modal views are a finicky way of presenting subviews, instead you should look at creating a simple view class to add to your view controller. You can then use [UIView animate...]; method to animate it in and out of view.
To get you started:
- (void)displayViewButtonPressed(id)sender
{
if (!self.topView)
{
UIView *overlayView = [[UIView alloc] initWithFrame:CGRectMake(44.0f, 22.0f, 40.0f, 44.0f];
[overlayView setAlpha:0.0f];
[overlayView setBackgroundColor:[UIColor redColor]];
[self setTopView:overlayView];
[overlayView release];
}
[self.view addSubView:self.topView];
[UIView animateWithDuration:0.5
animations:^{
[self.topView setAlpha:1.0f];
}];
}
In the above method we create a custom UIView and animate it into position. We maintain a pointer to it so we can remove it later (like so:)
- (void)dismissViewButtonTapped:(id)sender
{
[UIView animateWithDuration:0.5
animations:^{
[self.topview setAlpha:0.0f];
}
completion:^(BOOL finished) {
[self.topView removeFromSuperView];
}
}
Its a little more work that using modal views, but it gives you much more flexibility in regards to what you use and how you display it.
Hope this helps:)