In objective c ,i need get data from url in background (thread) with a period time.
¿ ideas ?
nsthread
dispatch
performSelectorInBackground
You could use GCD's dispatch_after()
// Delay execution of my block for 2 seconds.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do whatever you want in the background here.
});
Related
In Objective-C and Swift, is there any guarantee of order of execution for concurrent calls being made inside of a serial queue's async block?
Pseudo-code:
let serialQueue = SerialQueue()
let concurrentQueue = ConcurrentQueue()
serialQueue.async { // 1
concurrentQueue.async { // 2
run_task1() // task that takes 1 hour
}
}
serialQueue.async { // 3
concurrentQueue.async { // 4
run_task2() // task that takes 1 minute
}
}
In the above code, is task1 guaranteed to complete before task2 is called?
Or since they're called on a concurrent thread, the serial queue async only guarantees that run_task1 will be added to the concurrentQueue before run_task2, but not guarantee order of execution?
I've numbered the block in your question, so I can reference them here:
Block 1 and 3 are both running on a serial queue, thus block 3 will only run once 1 is done.
However, block 1 and 3 don't actually wait for task1/2, they just queue off work to happen asynchronously in blocks 2 and 4, which finishes near instantly.
From then on, both task 1 and 2 will be running concurrently, and finish in an arbitrary order. The only guarantee is that task1 will start before task2.
I always like to use the analogy of ordering a pizza vs making a pizza. Queuing async work is like ordering a pizza. It doesn't mean you have a pizza ready immediately, and you're not going to be blocked from doing other things while the pizzeria is baking your pizza.
Your blocks 1 and 3 are strongly ordered, so 1 will finish and finish before 3 starts. However, all the block does is order a pizza, and that's fast. It does mean pizza 1 (task 1) is done before pizza 2 (task 2), it just means you got off the first phone call before making the second.
I'm working on a timer that needs to do some calculations and run some functions at a certain interval. I'm trying to keep the interval as big as possible, but I need it to be kind of fine grained.
Here is the periodic timer with some of the stuff that needs to happen.
So as you can see, every second (the milliseconds passed % 1000 == 0) it will do some stuff if some conditions are met. But also every 10 milliseconds I need to check some stuff.
It seems this is a bit too much, and after running the timer for 2 minutes it already drags 1 second behind. I guess I'm approaching this the wrong way. Could/should I somehow put all that logic in a function that just runs async so the timer can just keep going.
It's not the end of the world if the timer display drags for a few milliseconds every now and then, if it catches up later. But now the whole timer just drags.
_timer = Timer.periodic(Duration(milliseconds: 10), (timer) {
passedMilliseconds = passedMilliseconds + 10;
// METRONOME BEEP AND BLINK
if (passedMilliseconds % currentTimerSettingsObject.milliSecondDivider == 0) {
_playMetronomeBeep();
_startMetronomeBlink();
}
// ONE SECOND
if (passedMilliseconds % 1000 == 0) {
secondsDuration--;
// COUNTDOWN
if (secondsDuration < currentTimerSettingsObject.countDown + 1) {
_player.play('sounds/beep.mp3');
}
// SET COUNTDOWN START VALUES
if (secondsDuration == currentTimerSettingsObject.countDown) {
isCountdown = true;
}
notifyListeners();
}
// TIME IS UP
if (secondsDuration < 0) {
switchToNextTimer();
notifyListeners();
}
});
}
You cannot rely on a timer to deliver events exactly on time. You need to use a more exact method than simply incrementing a counter by 10 on every tick. One example would be to start a Stopwatch before the timer and then (knowing that your ticks will only be on approximately 10ms intervals) read stopwatch.elapsedMilliseconds and base your decisions on that.
You will need to change your logic a bit. For example, you want to know when you pass a 1 second boundary. Previously, with your exact increments of 10 you knew you would eventually reach a round 1000. Now, you might see 995 followed by 1006, and need to deduce that you've crossed a second boundary to run your per second logic.
When I use typesAndWaits method with 2 seconds delay, I have to wait for 2 seconds in order to typing indicator display and when it is displayed I need to wait for another 2 seconds to display message.
I'm using BotMan chatbot service.
Here is my code:
$botman->hears('test', function (BotMan $bot) {
$bot->typesAndWaits(2);
$bot->reply('Prvo upiši svoje ime i prezime, i pritisnite SEND');
}
In the BotMan.php file, go to line 583 and replace
sleep($seconds);
With
usleep($seconds * 1000000);
It should work fine then...
I want to update the contents of this UITextView with this NSMutable array by adding some delay to it.
- (void)viewDidLoad{
[super viewDidLoad];
myArray = [[NSMutableArray alloc]initWithObjects:#"String1",#"String2",#"String3",#"String4", #"String5",..... nil];
int index = arc4random() % [myArray count];
myTextView.text = [myArray objectAtIndex:index];
I want to display this NSMutable array one after other with some delay in UITextView.
Is there some way to display array in UITextView with some delay.
Please help
Why you should use a timer
The correct way of doing this would be to use a repeating timer. The timer is configured to repeat and call a certain method every second.
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(updateText:)
userInfo:nil
repeats:YES];
Inside your (new) updateText method you would generate the random number and update the text.
- (void)updateText:(NSTimer *)theTimer {
int index = arc4random() % [myArray count];
myTextView.text = [myArray objectAtIndex:index];
}
This is a clean solution that is almost self documenting.
Why you shouldn't loop and perform after delay.
It is true that you could do this with performSelector:withObject:afterDelay: or dispatch_after() but it is a easy to get wrong and is the actual working solution is more complex and harder to understand.
If you think that you can just loop a certain number of times and inside call either of these then you are going to see something funny. Both these methods are asynchronous and will not wait for the call to be called. They are merely scheduling it to happen a specified time from "now".
What looping and calling asynchronous methods do
Loop
0 |----- 1s wait -----| |update|
1 |----- 1s wait -----| |update|
2 |----- 1s wait -----| |update|
3 |----- 1s wait -----| |update|
...
----------- time --------------------->
The result of this, as you can imagine, is that nothing will happen for one second. Then all the scheduled calls are going to happen all at once.
This is actually equal to performing the entire loop after one second.
|----- 1s wait -----| Loop:
0 |update|
1 |update|
2 |update|
3 |update|
...
----------- time --------------------->
You could make this work if you instead scheduled the next call after each update
|----- 1s wait -----| |update| |----- 1s wait -----| |update| ...
----------- time --------------------->
For this to happen you would have to schedule the next update in the previous update.
- (void)updateText {
int index = arc4random() % [myArray count];
myTextView.text = [myArray objectAtIndex:index];
[self performSelector:#selector(updateText)
withObject:nil
afterDelay:1.0];
}
This would do the exact same thing as the repeating timer but has two main disadvantages.
1) It is less intuitive.
In the timer example you would only have to read the timer code to understand that the text would update every second. In this case you would just call updateText. It is not intuitive by reading that code without looking at the implementation of updateText that this is a repeating process.
2) It gets even more complex if you want it to stop.
You can keep a pointer to an NSTimer and make it stop by simply calling [myTimer invalidate];. The code that uses either performSelector:... or dispatch_after() doesn't yet support it and if it was built to support that it would be even more complex and less intuitive.
Few ways to do, answer ranked according to my preference:
1.. You can use :
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats
2.. Grand Central Dispatch will also be serve you.
I am still new to cocos2d and was wondering if any of you guys can help me make a score timer. I seen some questions like this but looks like it is for a way older version of cocos2d. I want the timer to start at zero and go up in mins and seconds. Really appreciate any help or advice I get.
Start a NSTimer that runs every second and calls a method that updates the timer.
Define an integer called seconds and another called minutes in the header.
-(void)updateTheTime {
seconds++;
if (seconds == 60) {
seconds = 0;
minutes++;
}
label.text = [NSString stringWithFormat:#"%i:%i", minutes, seconds];
}