Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
There are 10 pages that I want to turn at different time intervals. I need to create 10 timers for flip? Or can I make an array intervals and to insert them to the timer? Сan I do it in a simpler way?
There are a lot of ways to do this. Here's one:
This is possibly a good solution if your intervals are irregular and far apart. If they are more evenly spaced (e.g. first is two seconds, next is four seconds) then you could simplify this design. But, I'm assuming that you just want to be able to pass in an array of intervals and then let the code take care of it all.
For this implementation, we're going to need an instance variable to hold an array of timers. Use a property if you prefer them to instance variables.
#implementation ViewController {
NSArray *_multipleTimerInstances;
}
Then some code to handle the timings.
- (void)multipleTimers:(NSArray *)durations {
// Get rid of any timers that have already been created.
[self mulitpleTimerStopAll];
NSMutableArray *newTimers = [NSMutableArray new];
// Create the new timers.
[durations enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
// Each element of the durations array specifies the flip interval in seconds.
double duration = [(NSNumber *)obj doubleValue];
// Schedule it.
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:duration
target:self
selector:#selector(multipleTimersFlip:)
userInfo:[NSNumber numberWithInteger:idx]
repeats:YES];
// Keep a reference to the new timer so we can invalidate it later, if we want.
[newTimers addObject:timer];
}];
// We now have a new list of timers.
_multipleTimerInstances = [newTimers copy];
}
- (void)multipleTimersFlip:(NSTimer *)timer {
NSInteger index = [timer.userInfo integerValue];
// The integer index corresponds to the index of the timer in the array passed
// to the multipleTimers method.
NSLog(#"Flip page for timer with index: %ld", (long)index);
}
- (void)mulitpleTimerStopAll {
// Get rid of any timers that have already been created.
for (NSTimer *timer in _multipleTimerInstances) [timer invalidate];
// And nil out the array, they're gone.
_multipleTimerInstances = nil;
}
Then you can invoke the timers like this:
[self multipleTimers:#[ #5.0, #10.0, #7.5 ]];
That's going to call back the multipleTimersFlip method every 5, 7.5, and 10 seconds.
Remember to call multipleTimersStopAll to stop all this going on when you don't need it.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm using Xcode with Objective C language. I wanted to know if there is any method to show a timer or a counter which shows as to how long the application is being running. It simple increments the counter to seconds, minutes however long the app is running. Any help would be appreciated.
Thank You
Create one UILable in your RootViewController or UIWindow and then update it frequently with following way.
create one Variable in .h file.
#property (nonatomic) int seconds;
put following code in ViewDidLoad method of your RootViewController
NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateLabel) userInfo:nil repeats:YES];
[timer fire];
Create following Function to update UILabel.
- (void) updateLabel {
self.seconds = self.seconds + 1;
NSLog(#"You can show time in minutes, hours and day also after doing some calculation as per your need");
[self.lblDemo setText:[NSString stringWithFormat:#"%d seconds",self.seconds]];
}
I want to use a speech synthesised sentence in an application demo. After pressing a button, a timer runs and after for example 12 seconds the first sentence is being spoken, then after 1.30min and so on.
The approach I was thinking of, is an NS Timer. But as far as I can see it only plays after a defined time. So do I need for any timespan a new timer? or can I track the time left and invoke a method call when a specific time is reached?
Thanks
I would do this using a dictionary with NSNumbers as the keys (representing seconds), and the sentence you want spoken as the value. Use a simple timer firing once every second, that updates an int, which (when converted to an NSNumber) would be checked against the dictionaries keys. I'm just logging in this example, but this should get you started,
- (void)viewDidLoad {
[super viewDidLoad];
self.dict = #{#3:#"First", #5:#"second", #11:#"Third", #35:#"Fourth"};
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(doStuff:) userInfo:nil repeats:YES];
}
-(void)doStuff:(NSTimer *) aTimer {
static int i = 0;
i++;
if ([self.dict.allKeys containsObject:#(i)]) {
NSLog(#"%#", self.dict[#(i)]);
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a game where when it ends, a gameover image (gameoverscreen.png) is visible (formerly hidden), and a button appears to play again. What I tried doing was creating a IBAction for it, then in that action, reloading the viewDidLoad.
example:
-(IBAction)restartGame:(id)sender{
[self viewDidLoad]; //to reload the screen
gameoverscreen.hidden = YES;
replayButton.hidden = YES;
}
I thought this would reload the screen, but it simply appears for half a second, then the gameoverscreen is visible again. I thought it had something to do with my NSTimer, but the timer is invalidated when the gameoverscreen.hidden = NO; so its not that.. Any reason on why it won't reload the screen properly, and allow the user to play again?
Well I can't answer the question per se but I can give advice... this is what I imagine your starting code looks like...
-(void)viewDidLoad
{
NSTimer *t = [some timer code to start the loop and process events]
//init some other state stuff, arrays of rects etc.
}
-(IBAction)restartGame:(id)sender{
[self viewDidLoad]; //to reload the screen
gameoverscreen.hidden = YES;
replayButton.hidden = YES;
}
this is what your code should look like:
-(void)viewDidLoad
{
[self restartGame];
}
- (void)setUpInitalGameState
{
//init some other state stuff, arrays of rects etc.
}
- (void)start
{
NSTimer *t = [some timer code to start the loop and process events]
}
-(IBAction)restartGame:(id)sender{
[self setUpInitialGameState];
[self start];
}
You should not be calling viewDidLoad to reset your game to a starting state. Let viewDidLoad only be called once automatically when the application launches, and then manually reset the variables and positions in your game. In viewDidLoad, you should load any images, audio, and initialize variables used in your games. Handle your game reset in a separate function with a format similar to the one below:
(IBAction)resetGame:(id)sender{
// Set positions of all images to a starting state.
// Change image visibilities as desired.
// Reset all game variables to the initial state.
}
My iOS game SlothDrop only calls viewDidLoad once. When the game ends, all objects are animated off screen and are repositioned, where they are later animated back on screen. At no time is the view loaded again, all objects are just moved around. You can see how I reset the game in the free version here: https://itunes.apple.com/us/app/slothdrop-free/id789603341?mt=8&uo=4
In this way you need wholly re-init your controller and then push it to the screen.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have an NSArray declared like this in my ViewDidLoad
animalz = [NSArray arrayWithObjects:#"rabbit",#"deer",#"ox", #"horse", #"cow", nil]; and I have a UIView subclass that I wrote which takes an NSString and rearranges it. The user presses a button and the number associated with the button is the number in the array that I need (Ex. if the number is three then I would need the value "horse" but if the button was 4 then I would need "cow"); Currently these numbers come in the form of long int and I can't get the corresponding value in the nsarray. I tried doing:
selectedani //this is the long int that represents the button
int indexani = [animalz objectAtIndex:selectedani];
NSString *anistr = [NSString stringWithFormat:#"%i",indexani];
[self rearrange:btistr];
This doesn't give me any compiler warnings or errors but when I press the button , the app crashes. What am I doing wrong and how can I fix it?
selectedani //this is the long int that represents the button
NSString *anistr = [animalz objectAtIndex:selectedani];
[self rearrange:anistr];
animalz is an array of NSString objects, but when you call [animalz objectAtIndex:selectedani], you assign the result to an int.
First of all, did you assigned selectedani before you used it? If not then you shouldn't use selectedani. It maybe the memory location or some other property of the button which may vary.
[animalz objectAtIndex:selectedani]
is returned an object, casting this object to an int not what you want and of course it's not an index too.
What can you do? Assign a tag number to the corresponding button dynamically, like
button.tag = 1;//or something like it
Then in the IBAction method retrieve the tag and use it to parse your array.
- (IBAction)buttonPressed:(id)sender
{
UIButton *pressedBtn = (UIButtton *)sender;
NSString *anistr = [animalz objectAtIndex:pressedBtn.tag];
//do what you want to do with the string
[self rearrange:anistr];
}
In this case, declare animalz as an iVar or property.
Everytime I am finished with my NSTimer, I want to invalidate it and create a new interval but it keeps the old interval as well as new interval. I want to invalidate NSTimes once I click the offButton. The timer stops printing "Working" but when I call my method with a different interval, it prints "Working" for both intervals.
My code is something like this:
-(void) fireTimer{
NSString *textValue = [sliderLabel text];
float value = [textValue floatValue];
[NSTimer scheduledTimerWithTimeInterval:value target:self selector:#selector(vibrate:) userInfo:nil repeats:YES];
}
- (void) vibrate:(NSTimer*)timer {
if(_offButton.selected){
[timer invalidate];
timer=nil;
}
NSLog(#"Working");
}
You aren't following the MVC design pattern by getting your values directly from the UITextField. Those values should be stored in a model object, with the MVC pattern being used to get any new values from the text field into the model. Your current implementation is very delicate and will break in the slightest breeze. It also requires this code to have access to the UI elements, which is very inflexible; it will be better to give it access to just the model object.
Store the NSTimer * as an instance variable, and note that if you are using ARC then the NSTimer retains the target (!!) so make this instance variable __weak to break the retain-cycle.
If you want your timer to repeat then there is no need to reset it at all; this only needs to be done if the user changes the time (see point 1!).
Move the if (button_selected) do_vibrate; code into the timer fired method.
The invalidation code that you use itself is correct. But it would be easier for you to keep a reference to your timer as an ivar or property.
In that case you would definetly avoid making multiple instances of a timer.