iOS image startAnimating isn't animating (most of the time) - ios

I have an animation that is not animating for some reason.
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBar.hidden = YES;
self.nameLabel.text = [self.name uppercaseString];
self.gradient1.alpha = .9;
self.gradient1.image = [UIImage imageNamed:#"heart.png"];
self.gradient1.animationImages = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"gradiant1.png"],
[UIImage imageNamed:#"gradiant2.png"],
...
[UIImage imageNamed:#"gradiant26.png"], nil];
self.gradient1.animationDuration = .5;
self.gradient1.animationRepeatCount = 1;
[self updateStats:nil];
}
-(void)updateStats:(NSTimer*)timer{
Utilities *utility = [[Utilities alloc] init];
[utility getDataWithSSID:self.ssID completion:^(bool *finished, NSArray *objects) {
if (finished){
...
[self.gradient1 startAnimating];
}
self.twoSecTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self
selector:#selector(updateStats:)
userInfo:nil
repeats:NO];
}];
}
Sometimes it animates once or twice and then stops even though the timer continues to hit over and over. Other times it just doesn't animate at all. However, I have a couple placeholder buttons that I put on the storyboard that aren't tied to anything and whenever I press one of the buttons it animates the next time the timer hits (Actually whenever I hit the screen even though I don't have any sort of gesture recognizers..). Also, when I add in all the other garbage I want to do in this ViewController it animates every other time it's being called. So I think it's something deeper than me forgetting so set some property.

It might be a better idea to move the animation trigger to a moment when that view is actually visible - hence to viewDidAppear:.
Also your way of creating a recursive timer scheduling makes me shiver. I guess it works fine for you but I would definitely suggest to use the repeats flag set to YES instead.
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBar.hidden = YES;
self.nameLabel.text = [self.name uppercaseString];
self.gradient1.alpha = .9;
self.gradient1.image = [UIImage imageNamed:#"heart.png"];
self.gradient1.animationImages = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"gradiant1.png"],
[UIImage imageNamed:#"gradiant2.png"],
...
[UIImage imageNamed:#"gradiant26.png"], nil];
self.gradient1.animationDuration = .5;
self.gradient1.animationRepeatCount = 1;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
//animate right away...
[self updateStats:nil];
//trigger new animations every two seconds
self.twoSecTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self
selector:#selector(updateStats:)
userInfo:nil
repeats:YES];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self stopUpdatingStats];
}
-(void)stopUpdatingStats
{
[self.twoSecTimer invalidate];
}
-(void)updateStats:(NSTimer*)timer
{
NSLog(#"updating");
[self.gradient1 startAnimating];
}

Related

How to recognize a touch event on UIImageView while animating in ios using objective c code?

Hi i am animating 4 images in UIImageView by the following code.
But the problem is image is not appearing in UIImageView. If i try removal of swipeImage code then image is appearing in UIImageView. How to make imageview appear in UIImageView ?
Oulet had made to UIImageView property, if i try to set image without animation code, UIImageView has image. Withanimation, UIImageView has no appearance of image. Thanks in advance for any help.
Property
#property (weak , nonatomic )IBOutlet UIImageView *imgslide;
Declaration
int scrlNo;
NSTimer *aTimer;
View did load code
scrlNo = 0;
imgslide.userInteractionEnabled = YES;
[self addGestures];
[self SwipeImages];
Add gesture code
-(void)addGestures //Adding Single Tap Gesture here
{
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageViewTap:)]; //init the TapGesture with the selector
singleTap.cancelsTouchesInView = YES;
[imgslide addGestureRecognizer:singleTap]; //Add it to imgslide, not to self.view
}
ImageViewTap code
-(void)imageViewTap :(UITapGestureRecognizer *) gesture
{
NSLog(#"Clicked image %d", scrlNo);
}
Swipe Images Code or animation code
- (void)SwipeImages
{
if (scrlNo==1) {
imgslide.image = [UIImage imageNamed:#"promo_banner_2.png"];
scrlNo=2;
[aTimer invalidate];
aTimer = nil;
aTimer=[NSTimer scheduledTimerWithTimeInterval:15
target:self
selector:#selector(SwipeImages)
userInfo:nil
repeats:YES];
}else if (scrlNo==0) {
// UIImage * img = [UIImage imageNamed:#"promo_banner_1.png"];
//
// [self.imageViewOutlet setImage:img];
imgslide.image = [UIImage imageNamed:#"promo_banner_1.png"];
scrlNo=1;
[aTimer invalidate];
aTimer = nil;
aTimer=[NSTimer scheduledTimerWithTimeInterval:15
target:self
selector:#selector(SwipeImages)
userInfo:nil
repeats:YES];
}
else if (scrlNo==2) {
// UIImage * img = [UIImage imageNamed:#"promo_banner_3.png"];
//
// [self.imageViewOutlet setImage:img];
imgslide.image = [UIImage imageNamed:#"promo_banner_3.png"];
scrlNo=3;
[aTimer invalidate];
aTimer = nil;
aTimer=[NSTimer scheduledTimerWithTimeInterval:15
target:self
selector:#selector(SwipeImages)
userInfo:nil
repeats:YES];
}
else if (scrlNo==3) {
//
// UIImage * img = [UIImage imageNamed:#"promo_banner_7.png"];
//
// [self.imageViewOutlet setImage:img];
imgslide.image = [UIImage imageNamed:#"promo_banner_7.png"];
scrlNo=0;
[aTimer invalidate];
aTimer = nil;
aTimer=[NSTimer scheduledTimerWithTimeInterval:15
target:self
selector:#selector(SwipeImages)
userInfo:nil
repeats:YES];
}
else if (scrlNo==4) {
}
}
Add this method & load this method on viewDidLoad instead of loading SwipeImages on viewDidLoad
-(void)addTimer
{
aTimer=[NSTimer scheduledTimerWithTimeInterval:15
target:self
selector:#selector(SwipeImages)
userInfo:nil
repeats:YES];
}
Then your viewDidLoad looks like
scrlNo = 0;
imgslide.userInteractionEnabled = YES;
[self addGestures];
[self addTimer];
And Edit SwipeImages to this,
- (void)SwipeImages
{
if (scrlNo==1) {
imgslide.image = [UIImage imageNamed:#"promo_banner_2.png"];
scrlNo=2;
}else if (scrlNo==0) {
imgslide.image = [UIImage imageNamed:#"promo_banner_1.png"];
scrlNo=1;
}
else if (scrlNo==2) {
imgslide.image = [UIImage imageNamed:#"promo_banner_3.png"];
scrlNo=3;
}
else if (scrlNo==3) {
imgslide.image = [UIImage imageNamed:#"promo_banner_7.png"];
scrlNo=0;
}
else if (scrlNo==4) {
}
}

Making a UILabel disappear

I am working on a kids app and need to make the answer disappear after a few seconds.
What do I need to add?
- (IBAction)calculate2:(id)sender
{
float aaaa = 6;
Answer2.text = [ [NSString alloc] initWithFormat:#"%.0f ",aaaa];
}
Use NSTimer and mention the specified time for UILabel to disappear:
- (IBAction)calculate2:(id)sender
{
float aaaa = 6;
Answer2.text = [[NSString alloc] initWithFormat:#"%.0f ",aaaa];
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(targetMethod:)
userInfo:nil
repeats:NO];
}
-(void)targetMethod:(NSTimer*)timer
{
//toggle hidden parameter
[Answer2 setHidden:!Answer2.hidden];
}
-(void) hideLabel
{
[Answer2 setHidden:YES];
}
just add [self performSelector:#selector(hideLabel) withObject:nil afterDelay:4] to calculate2
For hiding it non-animated it will be:
[label setHidden:YES];
But if you want to hide it with an Animation it could be:
[UIView animatedwithduration:1.0f delay:.35f animations:{
label.alpha = 0.0;
}completion:{
[label removeFromSuperview];
//Here you can put a completed code
}];
Hope it helps!

NSTimer automatically increases when I change view controller

In my viewController I inserted a timer for a calculation of numbers taken directly from my database of Parse.com.
The timer is working correctly, were inserted in viewDidAppear and in ViewDidDisappear in such a way as to lock the sequence when changing view controller.
The problem I have is that when I change the view controller with the Push the timer does not stop you give an example:
I open the application and the calculation is done correctly with the animation of NSTimer.
Change View, and then I go back with the back button to view where the timer at this point I see that the numbers contiunano to increase every time I change view and go back ...
Can you explain where I'm wrong?
-(void)viewDidAppear:(BOOL)animated {
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
[self.navigationController.navigationBar setBackgroundImage:[UIImage new]forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.shadowImage = [UIImage new];
[self.navigationController.navigationBar setBackgroundColor:[UIColor clearColor]];
self.title = NSLocalizedString(#"", nil);
[self animatelayertopoint:0];
[self AnimationMenuView:600];
[self QueryForViewPrincipal];
[self QueryForCollectionView];
[self ShowBadgeNumber];
[self Timer];
[collectionView reloadData];
}
-(void)Timer{
timer = [NSTimer scheduledTimerWithTimeInterval:0.012 target:self selector:#selector(CalcoloMediadiLaurea) userInfo:nil repeats:YES];
}
-(void) CalcoloMediadiLaurea{
PFUser *CurrentUser = [PFUser currentUser];
NSNumber *NumeroUndici = [NSNumber numberWithInt:11];
NSNumber *NumeroTre = [NSNumber numberWithInt:3];
NSNumber *ValoreMediaPonderata = [CurrentUser objectForKey:FF_USER_MEDIA_PONDERATA];
int FFValoreTre = [NumeroTre intValue];
int FFValoreUndici = [NumeroUndici intValue];
double MediaPonderata = [ValoreMediaPonderata doubleValue];
double RisultatoMoltiplicazioneValoriPonderataUndici;
RisultatoMoltiplicazioneValoriPonderataUndici = MediaPonderata * FFValoreUndici;
double RisultatoMediaLaurea;
RisultatoMediaLaurea = RisultatoMoltiplicazioneValoriPonderataUndici / FFValoreTre;
CalcoloMediaLaureaLabel.text = [NSString stringWithFormat:#"%.1f", FFTickValoreMediaLaurea ];
FFTickValoreMediaLaurea++;
if(FFTickValoreMediaLaurea > RisultatoMediaLaurea){
[timer invalidate];
timer = nil;
}
}
-(void)viewDidDisappear:(BOOL)animated {
[self animatelayertopoint:0];
[self AnimationMenuView:600];
[self CalcoloMediadiLaurea];
}
The timer get rescheduled again on view did appear without getting invalidated to the previous one.You should make instance of timer in .h and then hold the reference of timer in it .And on view did appear when you are scheduling the timer just invalidate it and then schedule it again.
if([self.timer isValid])
{
[self.timer invalidate];
self.timer=nil;
self.timer=[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(CalcoloMediadiLaurea:) userInfo:nil repeats:YES];
}
This worked for me which is along the lines of the above answer but a little more explicitly stated.
- (void)viewWillAppear:(BOOL)animated
{
NSTimeInterval secondsBetween = [endDate timeIntervalSinceDate:currentTime];
secondsLeft = secondsBetween;
[self countdownTimer];
}
- (void)viewDidDisappear:(BOOL)animated
{
[self.timer invalidate];
self.timer = nil;
}
//Initiates timer
- (void)countdownTimer
{
[self.timer invalidate];
self.timer = nil;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateCounter:) userInfo:nil repeats:YES];
}
It's because you are creating new timers without invalidating old ones. The timers don't get invalidated automatically, you have to do it yourself. So if U go on second view and return before your invalidate condition is true you will create new timer and have two of them :)... And so on.

Can't trigger function from NSTimer's selector

So here's my code :
- (IBAction)run:(id)sender {
animationPointer = 0;
self.animationArray = [[NSMutableArray alloc] init];
UIView *allViews = [[UIView alloc]
initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
for (int i = 0; i < [self.paths count]; i++) {
[allViews addSubview:[self createAnimation:[self.paths objectAtIndex:i]]];
[self.animationArray addObject:allViews];
}
timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(animateTurn)
userInfo:nil repeats:YES];
}
- (void)animateTurn {
UIView *tempView = [self.animationArray objectAtIndex:animationPointer];
[self.view addSubview:tempView];
for (UIImageView *view in tempView.subviews) {
[[tempView.subviews objectAtIndex:animationPointer] startAnimating];
}
animationPointer++;
if (animationPointer >= [self.animationArray count]) {
[timer invalidate];
}
}
createAnimation returns, as you would expect, a fully animated UIImageView. The plan is to have several on each UIView and then animate them all on a UIView then the next after half a second and it repeats. There's only one on each UIView for now.
However, when calling animateTurn on the NSTimer, the animations don't show up.
If I call the method via the normal [self animateTurn] then they appear but nothing with NSTimer nor the performSelector function.
Any help with this (or even suggestions for a better method)?
EDIT:
I should mention the function is actually being triggered and the code is being run including the startAnimating (checked with BOOL/NSLog). There is simply nothing being shown.
This is Your Solution:-
This is what I used and now the selector is Working. :-)
if (![NSThread isMainThread])
{ [self performSelectorOnMainThread:#selector(selectorToRunInMainThread) withObject:nil waitUntilDone:NO];
}
-(void)selectorToRunInMainThread
{
NSString *str = #"Timer event has fired";
NSTimer *atimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateModel:) userInfo:str repeats:YES];
}
Include this line after your timer:-
[timer fire];

UIImageView not redrawing when image set to nil

I am using a UIImageView to display both still and animated images. So sometimes, I'm using .image and sometimes I'm using .animationImages. This is fine.
Whether it's static or animated, I store the UIImages's in item.frames (see below)
The problem is that I'd like to display a UIActivityIndicatorView in the center of the view when the animation frames are loading. I would like this to happen with no images or frames in there. The line that isn't doing what it's supposed to is:
[self.imageView removeFromSuperview];
As a matter of fact, setting it to another image at this point doesn't do anything either. It seems like none of the UI stuff is happening in here. BTW,
NSLog(#"%#", [NSThread isMainThread]?#"IS MAIN":#"IS NOT");
prints IS MAIN.
The image that is in there will stick around until the new animation frames are all in there (1-2 seconds) and they start animating
This is all being run from a subclass of UIView with the UIImageView as a subview.
- (void)loadItem:(StructuresItem *)item{
self.imageView.animationImages = nil;
self.imageView.image = nil;
[self.spinner startAnimating];
self.item = item;
if (item.frameCount.intValue ==1){
self.imageView.image = [item.frames objectAtIndex:0];
self.imageView.animationImages = nil;
}else {
[self.imageView removeFromSuperview];
self.imageView =[[UIImageView alloc] initWithFrame:self.bounds];
[self addSubview:self.imageView ];
if( self.imageView.isAnimating){
[self.imageView stopAnimating];
}
self.imageView.animationImages = item.frames;
self.imageView.animationDuration = self.imageView.animationImages.count/12.0f;
//if the image doesn't loop, freeze it at the end
if (!item.loop){
self.imageView.image = [self.imageView.animationImages lastObject];
self.imageView.animationRepeatCount = 1;
}
[self.imageView startAnimating];
}
[self.spinner stopAnimating];
}
My ignorant assessment is that something isn't being redrawn once that image is set to nil. Would love a hand.
What I have found is not an answer to the question, but rather a much better approach to the problem. Simply, use NSTimer instead of animationImages. It loads much faster, doesn't exhaust memory and is simpler code. yay!
Do this:
-(void)stepFrame{
self.currentFrameIndex = (self.currentFrameIndex + 1) % self.item.frames.count;
self.imageView.image = [self.item.frames objectAtIndex:self.currentFrameIndex];
}
and this
-(void)run{
if (self.item.frameCount.intValue>1){
self.imageView.image = [self.item.frames objectAtIndex:self.currentFrameIndex];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1/24.0f target:self selector:#selector(stepFrame) userInfo:nil repeats:YES];
}else{
self.imageView.image = [self.item.frames objectAtIndex:0];
}
}

Resources