After creating an image at a random location (spawnGood), if that object collides with the user controlled image (userToken) an NSTimer should start to work which uses the 'stick' method. This method is supposed to move spawnGood to the same position as userToken if userToken is moved (eg. sticks itself to userToken). However, I get the 'unrecognised selector sent to instance' error when the two images collide. It may either be a problem with the timer or the method, so is anyone able to suggest a solution to this? Thanks in advance :)
The code below produces the described error:
-(void)spawn{
spawn = [NSTimer scheduledTimerWithTimeInterval:2.0f
target:self
selector:#selector(spawnMechanism)
userInfo:nil
repeats:YES];
}
-(void)stick:(UIImageView *)spawnGood{
[UIView animateWithDuration:3.0
delay: 0
options: UIViewAnimationOptionCurveLinear
animations:^{
spawnGood.center=CGPointMake(userToken.center.x, userToken.center.y);
}
completion:^(BOOL finished){
NSLog(#"complete");
}];
}
-(void)spawnMechanism{
timeSinceLastSpawn++;
if(timeSinceLastSpawn >= 3)
{
if( arc4random() % 10 < 7 ){
UIImageView *spawnGood;
spawnGood=[[UIImageView alloc]initWithFrame:CGRectMake(arc4random() % 700, -100, 70,70)];
UIImage *image;
image=[UIImage imageNamed:#"friendly-01"];
[spawnGood setImage:image];
[array addObject:spawnGood];
[self.view addSubview:spawnGood];
NSLog(#"spawnGood spawned");
[UIView animateWithDuration:2.0
delay: 0.0
options: UIViewAnimationOptionCurveLinear
animations:^{
CGRect frame1 =[spawnGood frame];
frame1.origin.y =frame1.origin.y+950;
[spawnGood setFrame:frame1];
}
completion:^(BOOL finished){
if(CGRectIntersectsRect(userToken.frame, spawnGood.frame)){
NSLog(#"Good Collision");
stick=[NSTimer scheduledTimerWithTimeInterval:rate
target:stick
selector:#selector(stick:)
userInfo:nil
repeats:YES];
}else{
[UIView animateWithDuration:2.0 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
CGRect frame1 =[spawnGood frame];
frame1.origin.y =frame1.origin.y+950;
[spawnGood setFrame:frame1];
}
completion:nil];
};
}
];
}
}
}
You have two errors:
the target in this line
stick=[NSTimer scheduledTimerWithTimeInterval:rate
target:stick
selector:#selector(stick:)
userInfo:nil
repeats:YES];
should be 'self', not 'stick' (which is presumably an NSTimer * class variable?)
the parameter of stick should be an NSTimer *, not an image view.
You should prettify your code and add more context.
Related
So i was trying my hands on animation. I have a UIlabel which i want to fade in on and fade out after certain period.
I successfully done it as shown in the first answer with the help of timer.
Animation done as shown in Answer 1
Now i want to restart this animation when my app comes foreground.
Problems :-
What should i do to restart animations?
I want that when app comes in foreground, UIlabel should act as if this is the first time i am starting animation. Basically remove all animation on UIlabel and do start animation fresh.
use like add the following method in your ViewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myMethod) name:UIApplicationWillEnterForegroundNotification object:nil];
-(void)myMethod
{
// start the beiging code here
//[self MyLabelAnimation];
[NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:#selector(MyLabelAnimation:) userInfo:nil repeats:NO];
}
You should do like this
#interface ViewController ()
{
NSTimer *timer;
}
#end
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(MyLabelAnimation:) userInfo:nil repeats:NO];
}
- (void)MyLabelAnimation:(NSTimer*) timer1 {
self->_mylabel.text = #"Hello";
[UIView animateWithDuration:0.3 animations:^{
self->_mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->_mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
self->_mylabel.text = #"Text 2";
[UIView animateWithDuration:0.3 animations:^{
self->_mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->_mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
self->_mylabel.text = #"Text 3";
[UIView animateWithDuration:0.3 animations:^{
self->_mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->_mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
self->_mylabel.text = #"Text 4";
[UIView animateWithDuration:0.3 animations:^{
self->_mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.0 delay:4.8 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->_mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
[self viewWillAppear:YES];
}];
}];
}];
}];
}];
}];
}];
}];
}
-(void)viewWillDisappear:(BOOL)animated
{
[timer invalidate];
}
You should read Looking to understand the iOS UIViewController lifecycle carefully.
The methods your are looking to use are
viewWillAppear and viewWillDisappear
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(MyLabelAnimation:) userInfo:nil repeats:NO];
}
// Your animation....
- (void)MyLabelAnimation:(NSTimer*) timer {
self->mylabel.text = #"Hello";
[UIView animateWithDuration:0.3 animations:^{
self->mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
self->mylabel.text = #"Text 2";
[UIView animateWithDuration:0.3 animations:^{
self->mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
self->mylabel.text = #"Text 3";
[UIView animateWithDuration:0.3 animations:^{
self->mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
self->mylabel.text = #"Text 4";
[UIView animateWithDuration:0.3 animations:^{
self->mylabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.0 delay:4.8 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self->mylabel.alpha = 0.0;
} completion:^(BOOL finished) {
[NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:#selector(MyLabelAnimation:) userInfo:nil repeats:NO];
}];
}];
}];
}];
}];
}];
}];
}];
}
Here is the answer for the question I have asked.
Inwit done it with the help of a bool variable which sets to No when app goes in background and will get set to yes when goes in foreground.
SO the next animation depends on the bool value.
Here is the link for the answer
Restart animation after pause
I have been trying to make my UILabel blink in Xcode
but the problem is it does not blink
Here is my code:
self.labelCountdownTime.alpha = 0.0;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDuration:1.0];
[UIView setAnimationRepeatCount:FLT_MAX];
self.labelCountdownTime.alpha = 1.0;
[UIView commitAnimations];
Is there something I'm doing wrong.
Thanks
You can use NSTimer to blink your text in UILabel like so:
NSTimer *timer = [NSTimer
scheduledTimerWithTimeInterval:(NSTimeInterval)(1.0)
target:self
selector:#selector(blink)
userInfo:nil
repeats:YES];
BOOL blinkStatus = NO;
And the selector will call this function:
-(void)blink{
if(blinkStatus == NO){
yourLabel.alpha = 1.0;
blinkStatus = YES;
}else {
yourLabel.alpha = 0.0;
blinkStatus = NO;
}
}
Or you can use method animationWithDuration of UIView like so:
self.yourLabel.alpha = 0;
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse animations:^{
self.yourLabel.alpha = 1;
} completion:nil];
Hope this will help you.
I Think you are wanting some thing more like the following:
Create a timer in your controller:
#property (strong, nonatomic) NSTimer *timer;
then start the timer where you need it to start, like maybe in viewDidLoad
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(toggleLabelAlpha) userInfo:nil repeats:YES];
and here is the selector:
- (void)toggleLabelAlpha {
[self.labelCountdownTime setHidden:(!self.labelCountdownTime.hidden)];
}
Try this ?
I need to animate a UIImageView inside my application, and cyclically change the UIImage inside it, making it look like an animated photo slideshow.
Right now I'm using an NSTimer to fire every N seconds the UIImage change and the animation itself:
- (void)viewDidLoad {
// NSArray initialization
NSTimer *timer = [NSTimer timerWithTimeInterval:16
target:self
selector:#selector(onTimer)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[timer fire];
[super viewDidLoad];
}
This is the onTimer selector code:
- (void) onTimer {
// cycle through max 9 images
if(imageIndex > 8)
imageIndex = 0;
// set the image
[_imageContainer setImage:[images objectAtIndex:imageIndex]];
// reset width and height of the UIImage frame
CGRect frame = [_imageContainer frame];
frame.size.width -= 170.0f;
frame.size.height -= 100.0f;
[_imageContainer setFrame:frame];
// fade in
[UIView animateKeyframesWithDuration:2.0f delay:0.0f options:0 animations:^{
[_imageContainer setAlpha:1];
} completion:^(BOOL finished) {
// image movement
[UIView animateKeyframesWithDuration:12.0f delay:0.0f options:0 animations:^{
CGRect frame = [_imageContainer frame];
frame.size.width += 170.0f;
frame.size.height += 100.0f;
[_imageContainer setFrame:frame];
} completion:^(BOOL finished) {
// fade out
[UIView animateKeyframesWithDuration:2.0f delay:0.0f options:0 animations:^{
[_imageContainer setAlpha:0];
} completion:nil];
}];
}];
imageIndex++;
}
This seem a very raw but "working" way to achieve what I want but I recognize it might not be the ideal way.
Is there any better method to achieve what I'm looking for?
Updated Answer For Fade Animation
- (void)viewDidLoad
{
[super viewDidLoad];
// self.animationImages is your Image Array
self.animationImages = #[[UIImage imageNamed:#"Image1"], [UIImage imageNamed:#"Image2"]];
// make the first call
[self animateImages];
}
- (void)animateImages
{
static int count = 0;
UIImage *image = [self.animationImages objectAtIndex:(count % [animationImages count])];
[UIView transitionWithView:self.animationImageView
duration:1.0f // animation duration
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.animationImageView.image = image; // change to other image
} completion:^(BOOL finished) {
[self animateImages]; // once finished, repeat again
count++; // this is to keep the reference of which image should be loaded next
}];
}
- (IBAction)press:(id)sender {
UIImage *bomb = [UIImage imageNamed:#"bom"];
UIImageView *bom =[[UIImageView alloc] initWithImage:bomb];
[bom setFrame: CGRectMake(83,115,35,35)];
[self.view addSubview:bom];
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationCurveEaseIn animations:^{
[bom setFrame:CGRectMake(149,47,35,35)];
}
completion:^(BOOL finished)
{
[bom setFrame:CGRectMake(134,40,60,55)];
[bom setImage:[UIImage imageNamed:#"splash"]];
hits++;
_hit.text=[NSString stringWithFormat:#"%i",hits];
}];
}
Here is my code! The object bom here handles the imageview for splash.png image and i want that image to be appeared only for 0.5 sec when each time the button is pressed
You could set up an NSTimer that calls a method which hides the image. You would have to keep a reference to the bomb.
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(hideImage) userInfo:nil repeats:NO];
-(void)hideImage {
self.bomb.hidden = YES;
}
I have a multiple images to show in imageview using cross dissolve animation and taping on image displays detail about image. Following is the code working but tap on imageview is failing when it's animating from one image to another.
Code for attaching single tap gesture recogniser to UIImageview and starting animation timer.
self.imageView.userInteractionEnabled = YES;
self.singleTapGestureRecogniser = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showDetails)];
self.singleTapGestureRecogniser.numberOfTapsRequired = 1;
self.singleTapGestureRecogniser.cancelsTouchesInView = NO;
[self.imageView addGestureRecognizer:self.singleTapGestureRecogniser];
[self startAnimationTimer];
- (void)startAnimationTimer
{
if(!self.timer && ![self.timer isValid]) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:#selector(startAnimation)
userInfo:nil
repeats:YES];
[self.timer fire];
}
}
Single tap on imageview works fine unless following code is executing! I have to tap 3-4 times to open details about image.
- (void)startAnimation
{
[UIView transitionWithView:self.imageView duration:2.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^ {
currentImageIndex = ++currentImageIndex % self.images.count;
[self.imageView setImage:[[self.images objectAtIndex:currentImageIndex] image]];
} completion:^(BOOL finished) {
}
];
}
Could someone please suggest me how to get rid of this issue please.
set UIViewAnimationOptionAllowUserInteraction in the options like so
[UIView transitionWithView:self.imageView duration:2.0
options:UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowUserInteraction
animations:^ {
currentImageIndex = ++currentImageIndex % self.images.count;
[self.imageView setImage:[[self.images objectAtIndex:currentImageIndex] image]];
} completion:^(BOOL finished) {
}
];