Why changing the frame of UISearchBar simply doesn't work - objective-c

CGRect rectSearchLocationFrame=self.rectsearchLocation;
CGRect rectSearchCityFrame = self.rectsearchCity;
rectSearchLocationFrame.size.width += change *changeByMuch;
rectSearchCityFrame.size.width -= change * changeByMuch;
rectSearchCityFrame.origin.x +=change*changeByMuch;
self.searchLocation.frame = rectSearchLocationFrame;
self.searchCity.frame = rectSearchCityFrame;
PO1(self.searchLocation.textField);
PO1(self.searchCity.textField);
//NSAssert(false, #"Hello");
I look carefully. self.searchLocation has indeed change frame
(lldb) po self.searchLocation
<BGSearchBar: 0x158e5130; baseClass = UISearchBar; frame = (0 38; 260 44); text = ''; opaque = NO; autoresize = W+BM; gestureRecognizers = <NSArray: 0x158d1ba0>; layer = <CALayer: 0x158e5220>>
You see, the frame? The width is 260 there, not 160. It shouldn't end in the middle.
Yet, this is the screenshot
If I animate the movement, it seems that it actually change size. However, it slowly goes back. Something make it goes back to it's original size.
I got this error:
invalid context 0x0. This is a serious error. This application, or a
library it uses, is using an invalid context and is thereby
contributing to an overall degradation of system stability and
reliability. This notice is a courtesy: please fix this problem. It
will become a fatal error in an upcoming update.

try this
[UIView beginAnimations:nil context:nil];
<duration of animation>
<change frame of your search bar>
[UIView commitAnimations];
or
[UIView
animateWithDuration:0.1
animations:^{
<change frame of your search bar>
}
completion:^(BOOL finished) {
}];

-(void) setActiveSearchBar:(BGSearchBar *)activeSearchBar
{
_activeSearchBar=activeSearchBar;
AssertMainThread
if (activeSearchBar==self.searchLocation)
{
[self vChangeFrameBy:1];
}
else if (activeSearchBar==self.searchCity)
{
[self vChangeFrameBy:-1];
}
else if (activeSearchBar==self.searchBusiness)
{
[self vChangeFrameBy:0];
}
}
I made a stupid bug
Look at the code above. There is an extra ; on the original code after the last else if
So the last else if was like this:
else if (activeSearchBar==self.searchBusiness);
{
[self vChangeFrameBy:0];
}
Which mean [self vChangeFrameBy:0]; is always called no matter what :(

Related

objective-c animations - how to set end position, direction and type

I've seen many examples and read tutorial on animations,
all examples look +- the same like so:
- (void)showAnimation
{
[UIView animateWithDuration:0.3f animations:^{
backgroundView.alpha = 1.0f;
}];
[UIView animateWithDuration:1.0f
delay:0.0f
usingSpringWithDamping:0.4f
initialSpringVelocity:0.0f
options:UIViewAnimationOptionCurveLinear
animations:^{
CATransform3D init = CATransform3DIdentity;
alertView.layer.transform = init;
}
completion:^(BOOL finished) {
if( [self.delegate respondsToSelector:#selector(alertViewDidAppear:)] && finished) {
[self.delegate alertViewDidAppear:self];
}
}];
}
what I'm failing to understand is in the animation block where:
1. I set the beginning position
2. set the end position
3. the direction of movement
4. type of animation (fly-in/ turn/ fade-in/appear etc.)
There is no "starting position". There is no "direction of movement" or "type of animation". Animation is a change over time. The view is a certain way at the time your code runs. UIView animation has 6 possible view properties. You change any of those in the animation block (which states the time) and the change is animated - that is, instead of the change just happening, kaboom, it is performed over the given time.
That's all there is to it (as far as UIView class-method animation is concerned).

Objective-C- animateWithDuration Completion block called early

Before you discredit this question as being asked before, please look at the details:
I have a simple animation of shrinking the frame of a view from it's normal size to a zero frame in the middle of the superview. In my completion block I remove the superview from its superview and remove the view controller from the parent view controller. The completion block is called immediately. Moreover, the BOOL parameter finished to the completion block equals YES. So when I check if the animation is finished it says that it is even when it's not and the view is prematurely removed. Here is my code:
- (void)closeWindow {
[UIView animateWithDuration:0.5
animations:^{
contentView.frame = [self getSchoolSetUpStartingFrame];
} completion:^(BOOL finished){
if(finished) {
[self.view removeFromSuperview];
[self removeFromParentViewController];
}
}];
}
- (CGRect)getSchoolSetUpStartingFrame {
CGRect startingFrame;
CGRect myFrame = self.view.frame;
float xPos = (myFrame.origin.x + (myFrame.size.width/2));
float yPos = (myFrame.origin.y + (myFrame.size.height/2));
startingFrame = CGRectMake(xPos, yPos, 0, 0);
return startingFrame;
}
Is there anything else that could be related to this problem that I haven't considered yet? I appreciate all the help.
I'd try changing the animation duration to .5f, and verify that contentView is not nil during the animation block.
Also, it might be easier to achieve this animation by using a transform
animations:^{
contentView.transform = CGAffineTransformMakeScale(.1f, .1f);
}

Collision Being Detected before Collision Takes Place

In the following code I try and to detect if the code is actually detecting collision. But before the bullet and line collides, the debugger says "Collided!"
//Collision Detector
-(BOOL)viewsDoCollide {
if(CGRectIntersectsRect(_bullet.frame, _line.frame)) {
return YES;
} else {
return NO;
}
}
//So that the turrets shoot
- (IBAction)shooterButton:(id)sender {
[self mover:(id)sender];
}
- (void)mover:(id)sender {
CGRect bulletFrame = _bullet.frame;
CGRect lineFrame = _line.frame;
[UIView animateWithDuration:2 animations:^{
CGRect newFrame = CGRectMake(bulletFrame.origin.x + lineFrame.origin.x - 14, bulletFrame.origin.y, bulletFrame.size.width, bulletFrame.size.height);
_bullet.frame = newFrame;
}];
bool collisionDetector = [self viewsDoCollide];
if (collisionDetector == YES) {
NSLog(#"Collided!");
}
}
I presume the collision is "taking place" before it does because I have a set position for the bullet. How do I "shoot" the bullet without using [UIView animateWithDuration]? Or, how do I actually get the code to detect the collision when it actually happens?
Your collision detection code is not within the animation that is running. You've asked the OS to animate from one frame to another, which will happen after this function has returned (on the UI thread).
So, you're detecting collisions before the animation has started.
If you want to do a 2D game, I recommend using something like Cocos2D. It has high-level support for what you want to do.

iOS why my UIImageView within collection view cell does not respond to scale transform properly?

I got a UICollectionViewCell with an icon within it. I would like the cell to visually indicate that the user has tapped on it.
I'm trying UIView's animateWithDuration: and am trying to scale the icon's transform by 1.2 to make it larger, then set it to identity to make it original size. I've used such code before with regular images, and it seemed to work.
I get strange behavior where the image within a cell scales up, as if it is pinned by the top left corner. However, when it is scaling back to identity, it does so as if it scaling from the center (as you would expect it to behave). The result is that there's an unpleasant shift of the image center from one position to the next in between two animations.
How can I properly scale images within UICollectionViewCells?
-(void)setSelected:(BOOL)selected
{
[super setSelected:selected];
if(selected)
{
//I tried this, does not seem to do anything
self.icon.layer.anchorPoint = CGPointMake(0.5, 0.5);
[UIView animateWithDuration:0.3 animations:^{
self.icon.transform = CGAffineTransformMakeScale(1.2, 1.2);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.4 animations:^{
self.icon.transform = CGAffineTransformIdentity;
}];
}];
DLog(#"selected");
}else
{
DLog(#"unselected");
}
}

Scaling UIView using transform after animating frame change causes UIView to jump back to original frame before scaling

I'm trying to scale a UIView (with animation) after I move it (with animation). The problem is, when the scaling animation begins, it jumps back to the original position. Why?
[UIView animateWithDuration:t delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
// Drop the ball
CGRect frame = coinView.frame;
frame.origin.y += d;
coinView.frame = frame;
coinView.shouldSparkle = NO;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
// Initial scale up for ball "poof"
coinView.transform = CGAffineTransformScale(coinView.transform, 1.5, 1.5);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
coinView.transform = CGAffineTransformScale(coinView.transform, 0.000001, 0.000001);
} completion:^(BOOL finished) {
[coinView removeFromSuperview];
}];
}];
}];
EDIT: This is how I generated my d:
static CGFloat groundPositionY = 325;
CGRect convertedFrame = [coinView.superview convertRect:coinView.frame toView:self.view];
CGFloat d = groundPositionY - CGRectGetMaxY(convertedFrame);
EDIT2: Okay, so I changed the second UIView animation to the following and I discovered that the jump (and the scale down) happens before the second animation occurs, i.e. when animateWithDuration:delay:options:animations:completion: is called.
[UIView animateWithDuration:5 delay:3 options:0 animations:^{
coinView.transform = CGAffineTransformScale(coinView.transform, 1.5, 1.5);
} completion:nil];
I tested your code and it works fine for me. How do you generate your d? and on which block exactly it goes back?
I found the problem...
The coinView is a subview of a child view controller's view. The problem comes from the fact that I overrode that child view controller's viewDidLayoutSubviews method to lay out all the coinView's, so whenever that method was called, the coin view would move back to its original position and size intended by the child view controller.
Thanks for all of your help, repoguy and sergio!!