How to implement countdown function like Yahoo's APP News Digest - ios

I can use CAShapeLayer and UIBezierPath to draw the circle, I can also use this property CAShapeLayer.strokeEnd to control the progress. But the fast scrolling of path and time , I do not know how to implement.
Now I think the approach is to calculate the time difference between the two , and then use the time difference to circulation .
For example, The time difference between the two is 1000 seconds , should I have to set strokeEnd and the middle of the Label 1000 cycles ? Or that implement good results it ?
thanks in advance!

Note : StrokeEnd accepts value between 0 - 1
Lets Say,
See in your case circle represents the remaining time it will take to appear new feed. lets say 3PM.
so 3 PM will be your nextFeedTime = 3PM and,
you got this feed at 12PM so feedTime = 12PM.
So now you will have start and end value of feedTime=12PM - nextFeedTime=3PM
So feedTime is 0 for strokeEnd and nextFeedTime is 1 for StrokeEnd.
When you open app you will got currentTime which is initially initialised with feedTime and later it will be replaced all the time with current time stamp.
Lets assume currentTime is 1 PM.
Now we can calculate ratio to animate strockEnd property
strokeEnd = currentTime / nextFeedTime
and animate strokeEnd accordingly. hope this will helps you!

Related

iOS: Animating Multiple UIBezierPaths (One After the Other)?

I have an array of UIBezierPaths, but I'm having trouble doing so.
I've tried calculating the beginTime by doing the following, but all it does is animate the first line, but not the rest of the lines (they just appear without an animation).
pathAnimation.beginTime = n * lineDuration;
pathAnimation.beginTime = n * lineDuration;
Well, that's your problem. That time is in the deep dark past.
You want a time in the future. Start by getting the CACurrentMediaTime() and now add the delay amount to that.

How to get the same time the update(currentTime:) function uses? (before it is called)

Question: The update(currentTime:) function in SKScene is called every frame with a currentTime argument. I'm wondering how to get the time from the same source update(currentTime:) uses without using the update function. I only found CFAbsoluteTimeGetCurrent() which is different.
Reason: To calculate timeSinceLastUpdate you need an instance variable called timeOfLastUpdate. To implement timeOfLastUpdate you need to set it to an arbitrary value before the first update which makes the first calculation of timeSinceLastUpdate incorrect. You could have a simple if statement to detect this or use optionals but that is an unneeded branch which could be avoided if I just set timeOfLastUpdate in didMoveToView(view:). And that is what I'm trying to do.
The first timeSinceLastUpdate will always be different from the rest. Typically one stores the absolute time from the previous update call and subtracts it from the current call's time to get a timeSinceLastUpdate. If the previous time doesn't exist because you're on the first pass through the render loop — it's set to zero or infinity or negative something or whatever sentinel value you initialized it to, just set your timeSinceLastUpdate to some nominal value for getting started. Something like your frame interval (16.67 ms if you're going for 60 fps) would make sense — you don't want game code that depends on that time interval to do something wild because you passed it zero or some wildly huge value.
In fact, it's not a bad idea to have logic for normalizing your timeSinceLastUpdate to something sane in the event that it gets foo large — say, because your user paused and resumed the game. If you have game entities (such as GameplayKit agents) whose movement follows some sort of position += velocity * timeSinceLastUpdate model, you want them to move by one frame's worth of time when you resume from a pause, not take a five-minute pause times velocity and jump to hyperspace.
If you initialize your previous time to zero, subtract, and normalize to your expected frame interval, you'll cover both the starting and unpausing cases with the same code.
You could always use coalesce:
let deltaTime = currentTime - (previousTime ?? currentTime).
On first loop, your deltaTime is 0 (Should be this) after that, it is the change
Of course previousTime must be an optional for this to work

Dispatch and Delay between calls

I'm making a clone for that old game Simon (a.k.a. Genius, in Brazil), the one with the for coloured buttons which the player needs to press following a sequence of colors.
For testing, interface has 4 coloured buttons
I created an array for the button outlets, for easy access:
var buttonArray:[UIButton] = [self.greenButton, self.yellowButton, self.redButton, self.blueButton]
Also, created another array to store the sequence of colors
var colors:[Int] = []
When a game starts it calls a function which adds a random number from 0 to 3 (index on buttonArray), and add this number to the colors array
After adding a new color the color sequence, the app needs to show the sequence for the user, so he can repeat it
For that, it calls the playMoves function, which uses a for loop the run through the colors array and change the alpha from the button, simulating a 'blink'
func playMoves(){
let delay = 0.5 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
for i in self.colors{
self.buttonArray[i].alpha = 0.2
dispatch_after(time, dispatch_get_main_queue(), {
self.buttonArray[i].alpha = 1
})
}
}
It changes the alpha from the button to 0.2 and then, after half a second it returns the alpha to 1. I was using dispatch_after, passing the 0.5 seconds and on the code block it returns the alpha, as you guys can see on the code above.
On the first run, it appears to do it correctly, but when the colors array has 2 or more items, when it runs the loop, although it has a 0.5 sec delay, it blinks all the buttons on the same time.
It's probably some dumb mistake I'm making, but I'm clueless on the moment.
I would appreciate very much all the help!
Thanks!
All of these dispatch_after calls are scheduled at nearly the same time, making them appear to blink at the same time. There are a couple of approaches that would solve this:
You could, for example, adjust the when parameter (the dispatch_time_t parameter) for each button to be offset from the original time (such that delay was, effectively i * 0.5 * Double(NSEC_PER_SEC)).
You could also use key-frame animation, but I'd suggest you first try fixing the delay in your dispatch_after approach first.

10 Band Equaliser using NOVOCAINE

Im trying to build a 10 band Equaliser using NOVOCAINE.
I copied the Equaliser.mm's code in viewWillAppear, and added 9 more Sliders in the xib file, and changed IBAction code too this :
-(void)HPFSliderChanged:(UISlider *)sender {
PEQ[sender.tag - 1].centerFrequency = sender.value;
NSLog(#"%f",sender.value);
}
What I want to know is if I am doing this the right way or not ? and the what will be range of the Sliders ? Like in HPF example, the slider range is 2k to 8k. Need some guidance here.
Thanks.
EDIT: after your comment, I think it is clearer what you are asking.
Take the code to instantiate a NVPeakingEQFilter:
NVPeakingEQFilter* PEQ = [[NVPeakingEQFilter alloc] initWithSamplingRate:self.samplingRate];
PEQ.Q = QFactor;
PEQ.G = gain;
PEQ.centerFrequency = centerFrequencies;
you need define 3 parameters: Q, G, and centerFrequency. Both Q and centerFrequency are usually fixed (QFactor in my case is a constant equal to 2.0).
So, you have 10 sliders: each one corresponds to a fixed centerFrequency. I suggested iTunes values: 32Hz, 64Hz, 125Hz, 250Hz, 500Hz, 1KHz, 2KHz, 4KHz, 8KHz, 16KHz. You do not want to change those values when the slider value changes.
What you want to change when the slider value changes is the gain (G). At init time, G can be set to 0.0. This means "no amplification/attenuation".
When the slider moves, you change G, so actually you would do:
PEQ[sender.tag - 1].G = sender.value * kNominalGainRange;
where kNominalGainRange is 12.0, so if sender.value goes from -1.0 to +1.0, G goes from -12 to +12.
Hope this helps.
What I want to know is if I am doing this the right way or not ?
you do not show much code, but HPFSliderChanged seems correct. If you have any specific issue you should describe it and post more code.
and the what will be range of the Sliders ?
Actually, there is no rigid rule when it come to equalisers. iTunes goes from -12db to +12db, but you could use different ranges (with the only caveat being distortion).
Like in HPF example, the slider range is 2k to 8k. Need some guidance here.
again, you can take iTunes equaliser as an example (32Hz, 64Hz, 125Hz, 250Hz, 500Hz, 1KHz, 2KHz, 4KHz, 8KHz, 16KHz), or you can google for images of real equalisers and see which bands they use.

How to specify an beginTime for an animation by using CFTimeInterval?

For my understanding, beginTime can be used to say "hey, start at exactly 12:00 'o clock". But how would I tell this with an CFTimeInterval type? I thought that this one is nothing more than a kind of "float" value to specify seconds.
Or what else would be then the difference to the timeOffset property that is specified in CAMediaTiming protocol?
What I missed in the docs: beginTime is in "core animation absolute time" so you've to get the current time and specify your offset from that:
// Start in 5 seconds
theAnimation.beginTime = CACurrentMediaTime() + 5;
You first need to convert to the layer's timespace like so:
let currentLayerTime = myLayer.convertTime(CACurrentMediaTime(), from: nil)
Then you can set the beginTime relative to the layer's now time. For instance, to make an animation begin in 2s:
myAnimation.beginTime = currentLayerTime + 2
You'll also likely want to set the fillMode to .backwards, so that you can set the final property value before you add the animation:
myAnimation.fillMode = .backwards
myLayer.someProperty = someFinalValue
myLayer.addAnimation(myAnimation, forKey: "myAnimationName")
No, that is not what beginTime does. It specifies a relative start time from its parent animation (by default multiple animations in a group all fire at once).
From the documentation:
Specifies the begin time of the
receiver in relation to its parent
object, if applicable.
timeOffset causes it to start animating at the frame it would be at at the offSet time, and when it reaches the end it loops around. In other words, imagine A,B,C,D,E are frames of animation this is what happends in various cases if you set beginTime or timeOffset to a value equal to when you hit frame C in the normal case.
Normal |A->B->C->D->E
beginTime: | A->B->C->D->E
timeOffset: |C->D->E->A->B
I think the documentation of CAMediaTiming Protocol is very bad. Time Warp in Animation is a thorough explanation(re-documentation) of all properties of CAMediaTiming Protocol.

Resources