0
votes

Somehow something in my code is disabling animations, and I cannot find it. I built a search bar in my app, it has a delegate call for begin and end editing. When it begins I have a animation block to change its size, and it works, but the animation when it ends does not. I have commented out EVERY line of code except for the animations and the delegate calls, and even set delays on the animation blocks and it is always set instantly, but interaction with the objects is delayed for the amount of time of the animation. Is there a reason why the animation is being disabled or a general way to figure out why the animations are skipping?

EDIT: Even disabling all the code for the delegates and having a animation block with a delay isn't working, the button is tapped and calls

- (void)cancelButtonPressed:(id)sender {
    [UIView animateWithDuration:5.0f delay:5.0f options:0 animations:^{
        self.layer.borderWidth = 1.0f;
        self.layer.borderColor = [UIColor redColor].CGColor;

    } completion:^(BOOL finished) {

    }];
}

which happens instantly, doesn't even delay for 5 seconds.

EDIT 2: I put the animation code in another block that can perform the code inside after a delay, the code does correctly delay but the animation still doesn't work.

Edit 3: Here is the code for the button that calls the cancelButtonPressed method.

cancelButton = [UIButton buttonWithType:UIButtonTypeSystem];
            [cancelButton setTitle:NSLocalizedString(@"Cancel", @"Cancel") forState:UIControlStateNormal];
            cancelButton.translatesAutoresizingMaskIntoConstraints = NO;
            [cancelButton addTarget:self action:@selector(cancelButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
            [self addSubview:cancelButton];

Edit 4: Here is a video of the animation issue. When I click the cancel button it is instantly shrunk, but the code is in an animation block that is supposed to take 5 seconds, here is the video and code.

Video: http://cl.ly/3x3k3H2m1Y2F

barItem is a UIBarButton item, its customView is my search bar UIView subclass.

[UIView animateWithDuration:5.0f animations:^{
                barItem.width = 200;
                CGRect addressBarFrame = barItem.customView.frame;
                addressBarFrame.size.width = 200;
                barItem.customView.frame = addressBarFrame;
            } completion:^(BOOL finished) {
                NSLog(@"COMPLETION!");
            }];

Edit 5: What Im really trying to do: The app I am working on is a web browser. I built a custom search bar view. The view is in a UIBarButtonItem that is inside a UIToolbar attached to the top of the screen. When the user taps inside the bar item, the text field becomes active and the keyboard displays, the frame of a view inside is animated to shrink and a cancel button appears (still part of this search bar UIView subclass). When the cancel button is tapped it calls a method inside the subclass, and that does some clean up, then calls its delegate method to my UIViewController, which will then animate the frame again to get bigger. The reason why I need to change the frame is because if the text field gets too small I need to make it bigger while editing, but then can make it smaller when editing is done.

The issue: When the text field becomes active, the frame is changed inside an animation block. The frame properly animates over the amount of time given and to the new set frame. When the cancel button is tapped, another animation block gets called to change the frame again, but no matter if this animation block is in the delegate method or in the UIView subclass, or whatever I try to animate, will NOT be animated. If I add a delay onto the animation block, it will still act as if the code was called outside of a animation block, although the completion block is called at the right time, and if I put the animation block inside a block that can delay the code it will properly be delayed but the animation still does not happen. Taps also do not affect the view until the animation time is done, like normal.

Edit 7: If i animate the cancelButtons frame, or background color It will work. So I thought maybe its an issue with the toolbar that it is in, but animating the background color of that also works. So I still have no idea why I can animate the frame of the bar item and the custom view (the custom view in the code above) before editing but cannot animate it after editing.

Edit 8: I have figured out the issue. It was an optical illusion the entire time. Even though setting the UIBarButtonItem's width inside a animation block, the surrounding bar items would automatically space out to the new frame. And even though the frame is really animating, the subviews are automatically in their correct place, but the sequence of the animation made it look like it really was animating everything correctly. The animation I was trying to do when editing was finished was more noticeable so I thought only that was not animating. Changing around some stuff makes it look better but I don't think its possible to have the bar button items to animate the way I want.

3
Can you try to put some NSLog in finished block and see when it gets printed or does that get printed at all. It may give some idea of what actually is happening.Yogi
what is layer here ?sanjeet
I'm not sure if '0' is even a valid value for the "options" parameter. That may be causing some strange behavior. Please refer to the UIView class reference and use a valid value such as "UIViewAnimationOptionCurveEaseInOut". Also, if you don't have any completion block you can simply use "NULL" for this parameter. Again, see the UIView class reference.Samuel W.
@Yogi the completion is called at the correct time, after the 5 seconds.Maximilian Litteral
@sanjeet this code is in my UIView subclass thats a search bar.Maximilian Litteral

3 Answers

0
votes

Revised

If your trying to commit animations when a programmatically induced search bar is canceled then something like this will do the trick:

@interface TableViewController : UITableViewController <UISearchBarDelegate>

@property (strong, nonatomic) UISearchBar *searchBar;

@end

- (void) viewDidLoad:(BOOL)animated {

UIView *searchbarView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 44)]; //This adds a container that will hold the search bar. 
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 40, 44)]; 
self.searchBar.showsCancelButton = YES;
[searchbarView addSubview:self.searchBar];
self.searchBar.delegate = self;
[self.view addSubview:searchbarView]; or add to whatever view you want.
}

This is where you might be going wrong:

When a search bar is canceled you have to have the method searchBarCancelButtonClicked: invoked:

-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self animateButton];
}

-(void)animateButton {
//Commit your animations here:
}
0
votes

Try this

[UIView animateWithDuration:5.0 animations:^{
        CGRect addressBarFrame = barItem.customView.frame;
        addressBarFrame.size.width = 200;
        barItem.customView.frame = addressBarFrame;
    } completion:^(BOOL finished) {
        NSLog(@"COMPLETION!");
    }];

or this

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:5.0];
CGRect addressBarFrame = barItem.customView.frame;
addressBarFrame.size.width = 200;
barItem.customView.frame = addressBarFrame;
[UIView commitAnimations];
0
votes

Have you write [UIView setAnimationsEnabled:NO]; Check in your code. Sometimes it creates problem with UIView animation.