How to use isAnimating in an iPhone app - iphone

I want to have a custom loading menu made from a series of stills, that loops 3 times and then reveals a picture. Currently the picture is visible from the start. I want to use isAnimating to find out when the loading animation has stopped, and either change myImage.hidden off, or have the UIImageView initially containing a white image, then being replaced with the picture when isAnimating returns NO.
Apple's website just says
- (BOOL)isAnimating
and that it returns a Boolean YES or NO.
but how do you use this?
I need things to happen depending on whether something is animating or not, so i do i put the result it returns in a variable and check that in the conditional of an if statement?
put it in an if statement itself?
or is it a while statement?
or is it like:
- (BOOL)isAnimating{
//stuff to do if it is
}
or am i just getting the whole concept entirely wrong?

I guess isAnimating method just tells you if an UIViewImage is actually performing an animation.
Since you just want to create a short loading before displaying your image, why don't you simply use a timer?
You can do something like this
- (void)startAnimation {
yourImageView.hidden = YES; // Keep you image hidden while loading
[yourLoadingAnimation startAnimating]; // Start you loading animation
NSInteger timeout = 2; // Duration in seconds of your loading animation
[NSTimer scheduledTimerWithTimeInterval:timeout target:self selector:#selector(stopAnimation) userInfo:nil repeats:NO]; // Set the timer
}
- (void)stopAnimation {
[yourLoadingAnimation stopAnimating]; // Stop your loading animation
yourLoadingAnimation.hidden = YES; // Hide your laading animation
yourImageView.hidden = NO; // Display your image
}

Related

How to prevent UIImage from continually replaying an animation

I am making a game and currently my "player" is animating as I've implemented (which is wrong at the moment) and it continually runs the animation from start to start because it always restarts from the beginning when the function is called. What is the best way to prevent this and let the animation run all the way through? Here is the code I'm using at the moment:
- (void) startAnimatingLeft
{
NSArray *images = [NSArray arrayWithObjects:img9,img10,img11,img12,img13,img14,img15,img16, nil];
[imageView setAnimationImages:images];
[imageView startAnimating];
animateTimer = [NSTimer scheduledTimerWithTimeInterval:0.6 target:self selector:#selector(nothingMovingLeft) userInfo:nil repeats:NO];
}
From UIImage documentation:
startAnimating
This method always starts the animation from the first image in the list.
So you shouldn't call this method if the image is already animating. You can call isAnimating method to check if image is animating.

Detecting when MapView tiles are displayed

Since - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView is not called when the tiles are loaded from cache, is there a way to know when all the tiles have been loaded (either from cache or from the mapping servers) and displayed?
Is there any delegation that intimates that tiles have been loaded ?
Here is some source code I wrote: https://github.com/jonathanlking/mapViewTest
Why don't you think about the problem like this;
When the map view will change, mapView:regionDidChangeAnimated: will be called.
From there mapViewWillStartLoadingMap: will be called.
Next mapViewDidFailLoadingMap:withError: or mapViewDidFinishLoadingMap: will be called if the tiles have been fetched from the server.
However if neither are called, you can assume the tiles are being loaded from the cache.
As mentioned, mapViewDidFinishLoadingMap is sometimes not called at all, especially if the map tiles are already cached, and sometimes it is called multiple times.
I notice that when it is called multiple times at the last call all of the tiles are rendered. So I think you can get this to work if you set up a 2 second timer after the map starts changing. Disable interactions so that the map does not continue to change, and enable user interactions when the timer goes off.
If mapViewDidFinishLoadingMap gets called reset the timer again for 2 seconds into the future. When the timer finally goes off, you should have a fully rendered map.
You will want to consider the other callbacks such as mapViewDidFailLoadingMap. Also test this on a noisy connection, since 2 seconds may not be long enough if it takes a long time to fetch the tiles.
- (void)restartTimer
{
[self.finishLoadingTimer invalidate];
self.finishLoadingTimer = [NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(mapLoadingIsFinished)
userInfo:nil
repeats:NO];
}
- (void)mapLoadingIsFinished
{
self.finishLoadingTimer = nil;
self.mapChanging = NO;
self.view.userInteractionEnabled = YES;
}
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView
{
if (self.mapChanging) {
[self restartTimer];
}
}
- (void)startLookingForMapChange
{
assert(self.mapChanging == NO);
if (self.mapChanging == NO) {
self.mapChanging = YES;
assert(self.finishLoadingTimer == nil);
self.view.userInteractionEnabled = NO;
[self restartTimer];
}
}

objective-c: Animate button before timer ends

I'm working on a very simple iPhone game that involves choosing the right colored button as many times in a row based on a randomized voice prompt. I have it set up so that if the button is one color and gets clicked, it always goes to a hard-coded color every time (e.g. if you click red, it always turns blue). The color change method is set up in an IBOutlet. I have a timer set up in a while loop, and when the timer ends it checks if the player made the right selection. The problem is that the button color change does not occur until after the timer runs out, and this causes a problem with the method used to check the correct answer. Is there a way to make this color change happen instantly? From what I've searched I know it has something to do with storyboard actions not occurring until after code executes, but I haven't found anything with using a timer. Here is a section of the method that calls the timer if the answer is correct:
BOOL rightChoice = true;
int colorNum;
NSDate *startTime;
NSTimeInterval elapsed;
colorNum = [self randomizeNum:middle];
[self setTextLabel:colorNum];
while (rightChoice){
elapsed = 0.0;
startTime = [NSDate date];
while (elapsed < 2.0){
elapsed = [startTime timeIntervalSinceNow] * -1.0;
NSLog(#"elapsed time%f", elapsed);
}
rightChoice = [self correctChoice:middleStatus :colorNum];
colorNum = [self randomizeNum:middle];
}
One of two things stood out
You're using a while loop as a timer, don't do this - the operation is synchronous.
If this is run on the main thread, and you code doesn't return, your UI will update. The mantra goes: 'when you're not returning you're blocking.'
Cocoa has NSTimer which runs asynchronously - it is ideal here.
So let's get to grips with NSTimer (alternatively you can use GCD and save a queue to an ivar, but NSTimer seems the right way to go).
Make an ivar called timer_:
// Top of the .m file or in the .h
#interface ViewController () {
NSTimer *timer_;
}
#end
Make some start and stop functions. How you call these is up to you.
- (void)startTimer {
// If there's an existing timer, let's cancel it
if (timer_)
[timer_ invalidate];
// Start the timer
timer_ = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:#selector(onTimerFinish:)
userInfo:nil
repeats:NO];
}
- (void)onTimerFinish:(id)sender {
NSLog(#"Timer finished!");
// Clean up the timer
[timer_ invalidate];
timer_ = nil;
}
- (void)stopTimer {
if (!timer_)
return;
// Clean up the timer
[timer_ invalidate];
timer_ = nil;
}
And now
Put your timer test code in the onTimerFinish function.
Make an ivar that stores the current choice. Update this ivar when a choice is made and make the relevant changes to the UI. Call stopTimer if the stop condition is met.
In the onTimerFinished you can conditionally call and startTimer again if you desire.
Hope this helps!

How can I continually update when UISlider is past a certain value?

I'm implementing a UISlider that allows users to select a position on a football field. The idea of the slider is for the field to scroll forward when the slider value is above a certain value (the section with the arrow).
My issue is that I can only respond to the slider on UIControlEventValueChanged - so the field will only scroll forward when the user is actually moving the slider. I'd like it to move forward as long as the value is above a certain amount.
Any idea how I can do this? (I'm open to any suggestion, including an implementation that does not use a UISlider, composite implementations, etc.).
Here's the implementation:
The easiest way to handle this is with a timer. Add an NSTimer instance variable to your class, named—for the sake of the example below—moveTimer, then set up something like this:
- (void)sliderChanged:(UISlider *)slider
{
if(slider.value > 5)
{
if(moveTimer == nil)
{
moveTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self action:#selector(move) repeats:YES];
}
}
else
{
if(moveTimer != nil)
{
[moveTimer invalidate];
moveTimer = nil;
}
}
}
- (void)move
{
// update the background behind your slider
}
I found a solution that works for me:
[self performSelector:#selector(sliderMoved) withObject:nil afterDelay:0.5];
I call the sliderMoved method after every 0.5 seconds when slider.value > 0.5.
Try setting the continuous property of the slider to YES.

how to get back in navigation view

hi i am new to iphone application. i am doing an application that consist of image picker and image view. i am displaying the image in imageview by selecting the image in image picker .. what i need is afetr 3 seconds i have to go back imagepicker how can i done this please give code for that
You want to create an NSTimer object.
NSTimer *theTimer = [NSTimer scheduledTimerWithTimeInterval:3.0
target:self
selector:#selector(pictureTimerFired:)
userInfo:nil
repeats:NO];
Where the target selector has a signature like:
- (void) pictureTimerFired:(NSTimer*)theTimer {
NSLog(#"Timer fired, closing picture");
}
You would remove the imageView in the opposite way you added it. i.e. it depends if it was added as a modal view or subview etc.