How to make UIImage move every hour? - uiimage

Hey so I'm working on a simple app and I want this image on a map to move closer hour by hour towards the user location. I can't figure out where to start, can anyone help?
Thanks!

Swift has a Timer class. There are several overloads for Timer.init. The newer block based one works like this:
let hour = TimeInterval(60 * 60) //60 seconds per min * 60 min per hour = 360 seconds per hour
let timer = Timer.init(timeInterval: hour, repeats: true) { timer in
//Do hourly update stuff here
}

Related

Millisecond counter from date using RxJS and Angular 14

I am trying to setup a counter from a specific date using RxJS on an Angular 14 project, but the counter seems wrong.
Milliseconds only change on the red spot, seconds are changing on the orange spot, but seconds should change at the blue spot, and milliseconds should countup on the orange and red spot combined. Am I correct?
What is my mistake in this code?
TS:
startTime = new Date("April 10, 2013 00:00:00").getTime();
elapsedTime = Date.now() - this.startTime;
count: Observable<number> | undefined;
this.count = interval()
.pipe(map(count => count + this.elapsedTime)
);
}
This is the placeholder:
{{ count | async }}
Thank you
The problem is that you are scheduling with interval a new notification every ms, but the app cant process and render each notification in 1m. That means that as time goes by, the difference between the notification count being process (your intended measure of elapsedTime) and the real elapsed time in ms gets bigger and bigger and thus the time seems to run slower.
The easiest way to prevent this is increase the interval time between emissions to avoid a backlog of notifications, and to calculate the elapsedTime against the startTime in each iteration.
this.count = interval(30).pipe(
map(count => Date.now() - this.startTime)
);
cheers

THREE.Audio filter not ramping up with linearRampToValueAtTime

I'm having a little trouble working with the linearRampToValueAtTime on a BiQuadFilter applied to a WebAudio.
The audio works ok, and the initial lowpass filter is applied.
Problem is, as soon as I use the linearRamp method to bring up the frequency, it seems to ignore the endTime parameter (or better, it's not time correctly).
Some code to explain it better.
Here's the instancing:
this.audioLoader.load( 'public/media/soundtrack-es_cobwebs_in_the_sky.mp3', buffer => {
this.sounds.soundtrack = new THREE.Audio(this.listener);
const audioContext = this.sounds.soundtrack.context;
this.biquadFilter = audioContext.createBiquadFilter();
this.biquadFilter.type = "lowpass"; // Low pass filter
this.biquadFilter.frequency.setValueAtTime(200, audioContext.currentTime);
this.sounds.soundtrack.setBuffer(buffer);
this.sounds.soundtrack.setFilter(this.biquadFilter);
this.sounds.soundtrack.setVolume(0.5);
this.sounds.soundtrack.play();
})
Until here, everything looks ok. The sound plays muffled as needed.
Then, after a certain event, there's a camera transition, where I want the sound to gradually open up.
As a endTime parameter, I'm passing 2 seconds + the internal context delta.
this.sounds.soundtrack.filters[0].frequency.linearRampToValueAtTime(2400, 2 + this.sounds.soundtrack.context.currentTime);
Expecting to hear the ramp in two seconds, but the sound opens up immediately.
What am I missing?
The linear ramp will be applied using the previous event as the startTime. In your case that will be audioContext.currentTime at the point in time when you created the filter. If that is sufficiently long ago it will sound as if the ramp jumps right to the end value. You can fix that by inserting a new event right before the ramp.
const currentTime = this.sounds.soundtrack.context.currentTime;
const filter = this.sounds.soundtrack.filters[0];
filter.frequency.setValueAtTime(200, currentTime);
filter.frequency.linearRampToValueAtTime(2400, currentTime + 2);

Minus from slider value in AfterEffects

I'm making a timer. When the minutes value reaches 60, it has to decrease by 60 and increment the hour. It's tracking a time lapse; the minutes is currently the time of the computation divided by 6 : each frame is 10 seconds in real life.
This is the code I have so far:
effect("Mins")(1)+Math.floor(((time*10)/6))+effect("MinAdd")("Slider");
if(effect("Mins")("Slider").value > 60) {effect("Mins")("Slider") -60;}
Unfortunately, it doesn't work, and I don't know why.
I'm not quite sure what your setup is there, but usually property values are read by reading the .value property and set through setValue(), so in your case e.g.
effect("Mins")("Slider").setValue(effect("Mins")("Slider").value - 60);
Personally I'd probably use something more along the lines of:
var currentsec = (time*10)/6);
var minute = Math.floor(currentsec / 60);
var sec = currentsec % 60;
effect("Mins")("Slider").setValue(minute);
effect("Seconds")("Slider").setValue(sec);
though in your case of course for minutes and hours.

Replacing NSDate value if two NSDate objects aren't equal

basically I'm writing an app and I want some of its values to update weekly - so, using NSDate and NSUserDefaults I currently have this scenario set out:
let userDefaults = NSUserDefaults.standardUserDefaults()
var startOfWeek: NSDate?
The above is global^
var referenceDate = NSDate.timeIntervalSinceReferenceDate()
while referenceDate > 604800 {
if referenceDate > 604800 {
referenceDate -= 604800
}
This basically takes the amount of seconds that have elapsed since the 1st of Jan 2001 and subtracts 604800, which is the amount of seconds in a week, until you have an amount of seconds that is less than a week. This amount of seconds is basically the amount of seconds into the week, you're in.
After this I then create a variable which is just the negative of how many seconds into the week we are, a variable which is the current time and use them to create a new date object which is the start point for the week:
var weekTimer: NSTimeInterval = (-referenceDate)
var startOfWeek = userDefaults.objectForKey("startOfWeekKey") as? NSDate
var currentTime = NSDate(timeIntervalSinceNow: 0)
if startOfWeek == nil {
startOfWeek = NSDate(timeInterval: weekTimer, sinceDate: currentTime)
userDefaults.objectForKey("startOfWeekKey")
}
else {
}
So basically it creates a value for the start of the week and saves it to NSUserDefaults under the key "startOfWeekKey" if the value doesn't already exist. If the value does already exist, because it's already been saved, it's happy with this value and nothing happens.
Now, we create a new value to compare to our startOfWeek value so we can test if we enter a new week.
var startOfWeekCheck = NSDate(timeInterval: weekTimer sinceDate: currentTime)
Now we compare them:
if startOfWeek! == startOfWeekCheck {
}
else {
println("New week begins") //update other, irrelevant stuff here
startOfWeek = startOfWeekCheck
}
No matter what, new week begins is always printed, I added the following line to check what was happening:
println("\(startOfWeek!) \(startOfWeekCheck)")
And it prints the same value to the logs
I'm pretty unsure what to do at this point. Did I mess up? Can you not compare the two date objects like that? Is this a ridicuously inefficient manner to create a way to reset/change something once a week?
Note, this is not the exact code, I typed this all by hand because the code is on my macbook and I'm on my desktop, so if there are any typos / w/e don't worry about it, no compile errors on my mac.
Thanks!
This looks way too complicated. There is no need to do all the date calculations yourself. Especially because you do them wrong. Not every week has 604800 seconds. In many timezones you have one week per year which has 601200 seconds, and one week which has 608400 seconds. Also known as Daylight saving time. There are even countries that skipped a whole day in one year.
You have to use NSCalendar and NSDateComponents for correct date calculations.
But I would do it completely different:
Save the next refresh date in NSUserDefaults (default to distantPast)
If today >= next refresh date: refresh & write new refresh date.
Something like this:
let calendar = NSCalendar.currentCalendar()
// If nextRefreshDate was never written by us (i.e. first start of app) it will containt distantPast, which is in year 1 or so
NSUserDefaults.standardUserDefaults().registerDefaults(["nextRefreshDate" : NSDate.distantPast()])
// since we registered a default value we will always receive a valid NSDate object, so we can force unwrap
let nextRefreshDate = NSUserDefaults.standardUserDefaults().objectForKey("nextRefreshDate") as NSDate
// equivalent to: (nextRefreshDate < today) || (nextRefreshDate == today)
if nextRefreshDate.compare(NSDate()) != NSComparisonResult.OrderedDescending {
println("Refresh")
let refreshSuccess = true // get from your internet download code
if refreshSuccess {
// don't save the next refresh date until the refresh was actually sucessful. This makes sure that we refresh on next launch if this refresh fails for some reason
var startOfCurrentWeek: NSDate?
if calendar.rangeOfUnit(.CalendarUnitWeekOfMonth, startDate: &startOfCurrentWeek, interval: nil, forDate: NSDate()) {
if let startOfCurrentWeek = startOfCurrentWeek {
if let startOfNextWeek = calendar.dateByAddingUnit(.CalendarUnitWeekOfMonth, value: 1, toDate: startOfCurrentWeek, options: nil) {
NSUserDefaults.standardUserDefaults().setObject(startOfNextWeek, forKey: "nextRefreshDate")
println("Next refresh scheduled for \(startOfNextWeek)")
}
}
}
}
}
else {
println("No refresh necessary. Next refresh scheduled for \(nextRefreshDate)")
}

Swift: Repeat action after a random period of time

Previously, with Objective-C I could use performSelector: in order to repeat an action after a random period of time which could vary between 1-3 seconds. But since I'm not able to use performSelector: in Swift, I've tried using "NSTimer.scheduledTimerWithTimeInterval". And it works in order to repeat the action. But there is a problem. On set the time variable to call a function that will generate a random number. But it seems that NSTimer uses the same number every time it repeats the action.
What that means is that the action is not performed randomly, but instead, after a set period of time that is generated randomly at the beginning of the game and it is used during all the game.
The question is: Is there any way to set the NSTimer to create a random number every time it executes the action? Or should I use a different method? Thanks!
#LearnCocos2D is right... use SKActions or the update method in your scene. Here is a basic example of using update to repeat an action after a random period of time.
class YourScene:SKScene {
// Time of last update(currentTime:) call
var lastUpdateTime = NSTimeInterval(0)
// Seconds elapsed since last action
var timeSinceLastAction = NSTimeInterval(0)
// Seconds before performing next action. Choose a default value
var timeUntilNextAction = NSTimeInterval(4)
override func update(currentTime: NSTimeInterval) {
let delta = currentTime - lastUpdateTime
lastUpdateTime = currentTime
timeSinceLastAction += delta
if timeSinceLastAction >= timeUntilNextAction {
// perform your action
// reset
timeSinceLastAction = NSTimeInterval(0)
// Randomize seconds until next action
timeUntilNextAction = CDouble(arc4random_uniform(6))
}
}
}
use let wait = SKAction.waitForDuration(sec, withRange: dur) in your code. SKAction.waitForDuration with withRange parameter will compute random time interval with average time = sec and possible range = dur
Generate a random time yourself and use dispatch_after to do the action.
For more information on dispatch_after, see here. Basically you can use this instead of performSelector

Resources