Time Intervals in Objective C - objective-c

I am very very new to Objective C and x-code. I just started learning it last week. so sorry if the question is too simple.
I am doing a game more like a visual novel so its very simple and story board based app, but I have a question regarding displaying my choices. I want the choices to appear after my cut scene ends. is there any way I can add something like time-interval breaks so they only appear after certain time. can some one please guide me on how to go about it.

You can use NSTimer:
[NSTimer scheduledTimerWithTimeInterval:2.0f
target:self
selector:#selector(displayChoiceTimerFired:)
userInfo:nil
repeats:NO];
This will schedule a timer that will execute the displayChoiceTimerFired: method after 2 seconds. (The argument of that method is the timer itself.)
Or you can also use NSObject's perform methods:
[self performSelector:#selector(displayChoice:) withObject:nil afterDelay:2.0f];

Depending on how you are displaying your cut scenes, the safer way to display these UI elements would be to somehow trigger an action when your cut scene ends. The problem with the NSTimer Implementation I can foresee is if, for whatever reason, your cut scene takes longer to play than your NSTimer interval is set to, then your UI Elements are displayed prematurely. Just my two cents on a different, but what I believe to be a more elegant approach.

[self performSelector:#selector(displayChoice:) withObject:nil afterDelay:1.0];
You can use this method...where after delay is number of seconds

Related

How can I make an animated timer

Hi I need to make an animated timer like this:
for an iPhone Application using Objective C.
I really don't know what to do. Any Helps?
Thanks.
Have a look at DACircularProgress, it implements a circular progress view. As others said, you would increment the progress value with a NSTimer.
Just calculate the angle from the top using the ratio between elapsed time and the total time. Seems really simple. The timer can fire regularly and redo this calculation.
The image above looks like there are two circles with the same midpoint but slightly different radius superimposed on each other. The timer firing could also update this display.
It could also update the labels inside the circles, but I really do not understand "2 days 24 hours"....
That timer looks like it can be made using a pie chart with a mask on top of it.
Actually, you can use a png with the black circle transparent and draw the pie chart behind.
[edit] my answer assumes you know how to handle the timer part. If you want, I could also give you some info on that
This code starts a timer that would fire a function every two seconds
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(timePassed) userInfo:nil repeats:YES];
You can then make a function like this
-(void)timePassed {
//draw a bigger pie chart than the previous
//you can store the previous size inside a class property or global var
}
Don't forget to stop the timer when you're done with it
[self.timer invalidate];
This is a relative question I answered before (if u are only focusing on using the NSTimer to do animation )
Objective c - NSTimer, CADisplayLink, Thread
Hope it helps you

Is there a way to programmatically "tap" UIControls such as segment buttons?

I hope that the answer to my question may be useful to a lot of developers and fear that it is a really stupid question: I have a routine that graphically and programmatically shuffle cards in 5 different ways (including cut and deal.) This is implemented from a UISegmentControl, replacing a 5-button Modal Alert. This all works very well but here is the problem: When it is the computer's turn to deal I built a for-loop inside a for-loop to trigger random number generated calls to the shuffling graphic routines a random number of times < 10. All of the calls seem to be executed for the entire for-loops sets before any graphics show up on the screen. Then I see face-down and face up cards moving all over the screen. Psychedelic, right? It seems that my control loop logic is executing without blocking or waiting or serializing the graphics. Remember that the graphics work fine when the user is tapping one segment at a time. I have been considering implementing a UITouchEvent to programmatically simulate tapping the buttons but I haven't found a single example. Is it possible to programmatically "tap" the segment "buttons"?
you can do something like:
- (void)simulateButtonPressed {
[button sendActionsForControlEvents:UIControlEventTouchDown];
button.highlighted = YES;
[NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:#selector(simulateButtonTimeElapsed:) userInfo:nil repeats:NO];
}
- (void)simulateButtonTimeElapsed:(NSTimer *)timer {
button.highlighted = NO;
[button sendActionsForControlEvents:UIControlEventTouchUpInside];
}

Observer pattern for stopwatch

I'm trying to implement a stopwatch based on the MVC model.
The stopwatch uses the NSTimer with the selector -(void) tick being called every timeout.
I've tried to make the stopwatch as a model for reusability but I've run into some design problems regarding how to update the view controller for each tick.
First I created a protocol with the tick method and made the view controller its delegate. The view controller then updates the views based on the timer's properties at each tick. elapsedTime is a readonly NSTimeInterval.
It works, but I'm thinking it might be bad design. I'm an Objective-C/Cocoa Touch beginner. Should I be using something like KVO? Or is there a more elegant solution for the model to notify the view controller that elapsedTime has changed?
The timer is a good way to make sure that you update your user interface periodically, but don't use it to keep track of time. NSTimer can drift, and any small errors can accumulate if you use a timer to accumulate seconds.
Instead, use NSTimer to trigger a method that updates your UI, but get the real time using NSDate. NSDate will give you millisecond resolution; if you really need better than that, consider this suggestion to use Mach's timing functions. So, using NSDate, your code might be something like this:
- (IBAction)startStopwatch:(id)sender
{
self.startTime = [NSDate date];
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(tick:)
userInfo:repeats:YES];
}
- (void)tick:(NSTimer*)theTimer
{
self.elapsedTime = [self.startTime timeIntervalSinceNow];
[self updateDisplay];
}
- (IBAction)stopStopwatch:(id)sender
{
[self.timer invalidate];
self.timer = nil;
self.elapsedTime = [self.startTime timeIntervalSinceNow];
[self updateDisplay];
}
Your code might be a little more sophisticated if you allow restarting, etc., but the important thing here is that you're not using NSTimer to measure total elapsed time.
You'll find additional helpful information in this SO thread.
I would recommend against KVO for this problem. It introduces a lot of complexity (and several annoying gotchas) for little benefit here. KVO is important in cases where you need to ensure absolutely minimal overhead. Apple uses it a lot in cases for low-level, high-performance objects like layers. It is the only generally-available solution that offers zero-overhead when there is no observer. Most of the time, you don't need that. Handling KVO correctly can be tricky, and the bugs it can create are annoying to track down.
There's nothing wrong with your delegate approach. It's correct MVC. The only thing you need to really worry about is that NSTimer doesn't make strong promises about when it's called. A repeating timer is even allowed to skip in some cases. To avoid that problem, you generally want to calculate elapsedTime based on the current time rather than by incrementing it. If the timer can pause, then you need to keep an accumulator and a "when did I last start" date.
If you need higher-accuracy or lower-cost timers, you can look at dispatch_source_set_timer(), but for a simple human-targeted stopwatch, NSTimer is fine, and an excellent choice for a simple project.
Lately, I have been using using blocks instead of plain old #selector's. It creates better and code and keeps the logic on the same location.
There's no native blocks support in NSTimer, but I used a category from https://gist.github.com/250662/d4f99aa9bde841107622c5a239e0fc6fa37cb179
Without the return selector, you keep the code in one spot:
__block int seconds = 0;
NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:1
repeats:YES
usingBlock:^(NSTimer *timer) {
seconds++;
// Update UI
if (seconds>=60*60*2) {
[timer invalidate];
}
}];

How should the model update the UI of its progress?

I am trying to solve a problem in Objective-C, but I don't think the question is language specific.
I have to do some processing down in a model class that has no notion of UI. However, this processing takes some time and I want to let the user know the status via a progress bar.
My first attempt at this was defining a notion of a progress handler protocol/interface with some methods like
-startOperation;
-updateProgress:(double)currentValue ofMax:(double)maxValue
-endOperation;
This way my UI can implement that the the model need not know details about what goes on other than someone wants progress updates. Currently my UI unhides a progress bar, and updates it, then hides it when done. So far so good.
However, it turns out that sometimes this operation processing is very fast. Such that the UI updates result in a pretty disconcerting flicker as they execute. I don't know if the operation will be fast or slow beforehand.
One idea I had was to force the operation to take at least a certain duration to avoid the UI changes being so jarring to the eye, but this seemed to put knowledge of the UI in the model class, which must be wrong.
This would seem to be a common issue with (hopefully) some known pattern.
How would you address this?
Jonathan's and Darren's answers cover your actual problem, but I would add something regarding the question in the title: "How should the model update the UI of its progress?"
The answer, of course, is that it shouldn't. The model shouldn't have to know anything about any protocols for displaying data. There should be one uniform bindings layer taking care about propagating information from the model to the interface. Fortunately, Cocoa already includes such a bindings mechanism: Key-Value Observing.
What you should do is define a property on any model class where the concept of progress makes sense, something like #property (assign) float progress. Then you make sure the class is KVO compliant. Controller code that want to keep track of the progress simply registers to observe this value with something like:
[theObject addObserver:self forKeyPath:#"progress" options:0 context:NULL];
Make sure to read the documentation for the NSKeyValueObserving (KVO) informal protocol.
Also, you might want to have a look at Mike Ash's KVO-related notes and code: Key-Value Observing Done Right.
You can use NSTimer to delay the display of your progress bar until your operation had run for a given amount of time, say half a second:
-(void)startOperation {
// Show the progress bar in 0.5 seconds
if (!_timer) {
_timer = [[NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:#selector(showProgressBar:)
userInfo:nil
repeats:NO] retain];
}
}
In -endOperation, you cancel the timer and hide progress bar:
-(void)endOperation {
[_timer invalidate]; // cancel the timer
[_timer release];
_timer = nil;
[self hideProgressBar];
}
If the operation completes in less than 0.5 seconds, the timer is canceled before the progress bar is displayed.
One thing commonly done is to have your progress bar implementation not show itself right away, and apply some heuristic based on the first couple of updates (or a timeout) to determine whether it needs to show itself at all. That's how the Java ProgressMonitor behaves, for example. (The ProgressMonitor is a nice abstraction that separates the knowledge of progress from its graphical representation).
Once the progress widget is showing, you could repaint it on a leisurely timer, say 10 times per second, rather than reacting to every progress change event with a repaint.

"scheduledTimerWithTimeInterval:" problem in cocos2d?

I am trying to developed a iPhone app by using cocos2d. I using "scheduledTimerWithTimeInterval" for calling a method that called a fixed time interval. But now time interval increases in gradually. for this reason the time is slow in gradually.
here is my code:
- (void) methodTime: (id) sender{
NSTimer *rat =[NSTimer scheduledTimerWithTimeInterval:(.5) target:self selector:#selector(rotation:) userInfo:nil repeats:YES];
}
- (void) rotation:(NSTimer *)theTimer{
NSLog(#"I m # %i", i);
i=i+10; // Here , i is a global int variable.
i=i % 1440;
if(i==0){
[theTimer invalidate];
}
else {
int rotationNum=i;
Sprite *sp = [Sprite spriteWithFile: #"1.png"];
sp.position=cpv(220,180.5);
sp.rotation=rotationNum;
[self add:sp];
}
}
It looks like every 0.5 seconds you are adding a sprite to some list of sprites. Eventually the list is getting very large and all that data causes your method to take longer than 0.5 seconds to execute. This causes the timer to fire fast as it can, which is not all that fast since its always waiting for your method to be finished with.
Without know more about your code, that's my best guess.
Don't use NSTimer. Check out cocos2d best practices.
I had trouble understanding your question. You haven't even used one quotation mark in your 'question'.
Is it possible that your code needs more than 0.5 seconds to execute? Especially because the amount of work done in the background increases each iteration. (More sprites.)
Try to make this function faster, for example load that PNG into memory and don't load it each time from the file. (That's better for memory anyway.)
Btw: That loop looks dangerously like an infinite loop. (Though could be that it works…)
If all you're doing is continually rotating the object, CATransforms and Core Animation might be a better bet.
I would use Cocos2d-iphone's built in intervals.
Go through the demo cocos project and you will see how things like this "should" be done in the cocos framework.