Adjust a "for" loops duration - objective-c

I'm currently working on an app that will show a label that will start at zero, and count up to a number I specify. I wanted to do this using a simple loop like this one.
for (counterInt = 0; counterInt < 10; counterInt++)
{
NSLog(#"%i",counterInt);
}
The problem is, that this loop executes in less time than it takes for the view to appear on screen. My console logs 1-9 before the view finally loads with the label with showing 9. I've been researching for several hours trying to find a way to specify a duration for the loop and I can't seem to find any thing on this.
So my overall question is, is it possible to specify how long the loop should take to execute? If so, if anyone can point me in the right direction here it would be greatly appreciated!

Even if you slowed down the loop, it still wouldn't work. UI elements are only updated at the end of the run loop. You need to set up a timer and update the label in the method fired by the timer.

You're using the wrong approach. Try an NSTimer.
[NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:#selector(incrementLabel:)
userInfo:nil
repeats:YES];
Then create a method called incrementLabel and have it increment an instance variable and update the label accordingly.

You can sleep a thread:
[NSThread sleepForTimeInterval:1];
However, jrturton and james supply the correct approach. I would place James' code in the viewDidAppear method so your label starts where you want it and the counter begins when the view appears.

Related

Using for loop to add to an array, objects aren't being added until for loop is completely done looping

So, I am using the code below to cycle through json arrays if the json array returns positive, I add the json array to another array containing all of total arrays. This can take some time to complete however, because it is going through several different json urls plugging in different dynamic information.
I edited the code below to show more basic information. My problem is that data isnt actually entered into the array until the for loop is finished. I need it to be added as soon as it finds it, not after it runs through all the onlineChannels.count - Any help?
for (int i = 0; i<onlineChannels.count; i++) {
[jsonResults addObject:[parsingJson objectAtIndex:0]];
NSLog(#"%i",jsonResults.count);
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
[self.tableView reloadData];
} else {
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
[self.tableView reloadData];
}
}
My problem is that data isnt actually entered into the array until the for loop is finished.
How do you know?
I see that you're calling -reloadData, so perhaps you're expecting the change to be reflected in your table immediately? I believe that your objects are being added to the array immediately, but the change isn't displayed on the table right away. -reloadData doesn't actually redraw the table -- drawing happens as part of the main run loop. You're probably running this code on the main thread, and by doing so you're preventing the run loop from getting any time to redraw the table.
The best way to solve this sort of problem is to move time consuming processes like your loop to background threads. That will leave the main thread free to redraw the table as necessary, and it'll make your app more responsive as well.
Also, making the table reload all its data every time you add a single item even when that item's row isn't being displayed seems quite wasteful. Consider instead calling a method like reloadRowsAtIndexPaths:withRowAnimation: to update only the part of the table that has changed.

Objective-C iOS, set a delay for an update of text

I'm trying to find a solution to a problem I just stumbled upon.
Tried to search for it but it's not that I'm looking for.
I'm doing a GPS-app with two tabbars. I track the distance in the map-view (using CLLocation) and when I change tab to a different view the stringtext that say what distance it is from when I started don't update immediately, it take a couple of seconds.
And when I press the stop button I want it to either wait those couple of seconds so the real distance updates. But I dont want to freeze the app.
(*NSDate future = [NSDate dateWithTimeIntervalSinceNow: 3.0 ];
[NSThread sleepUntilDate:future];)
I'm saving the string with the distance in a cell in the second tab, so if I multitask while the app is going I want to just start the app and press stop. And then the new distance will be correct and saved. Hope I didn't confuse you with this much text I hope you understand what I asking for!
thx
[label performSelector:#selector(setText:) withObject:newText afterDelay:3.0];
So what you want to do is use dispatch_after:
dispatch_after(3 seconds, dispatch_get_main_queue(), ^
{
myLabel.text = <the value you want to appear>;
} );

How to access the remaining time of a non repeating NSTimer

I'm trying to access the remaining time of an NSTimer X. I want to update the title of a button every second to reflect remaining mm:ss until zero. I couldn't find anything here.
For example: [btY setTitle:[What to insert here?] forState:UIControlStateSelected];
Or would you rather solve this in a different way?
You can use fireDate
NSTimer *timer = [NSTimer timerWithInterval:1.0 target:self selector:#selector(updateButton) userInfo:nil repeats:YES];
- (void)updateButton:(NSTimer*)timer
{
float timeRemaining = timer.fireDate.timeIntervalSinceNow;
// Format timeRemaining into your preferred string form and
// update the button text
}
This is generally not how you would solve this.
Create a repeating NSTimer set to the resolution at which you want to update the button instead.
So for instance, if you want your button to change every second until zero, create a NSTimer like so:
NSTimer *timer = [NSTimer timerWithInterval:1.0 target:self selector:#selector(updateButton) userInfo:nil repeats:YES];
Then implement updateButton; basically have a counter for remaining seconds, and every time updateButton gets called, decrease the counter by one, and update the title of the button.
You will not be able to get this kind of information, instead you will need to run the timer several times, for example, if you want to update the button with a text one time each 30 seconds, instead of starting a timer with 30 seconds start a timer with 1 sec and repeat it 30 times

NSTimer in a for loop

I want to call the getData method after waiting 2 seconds each time this loop...loops. I've written out the NSTimer a number of times inside and outside the loop but can't get the correct usage for it to do what I want.
for (TwitterPerson *person in [tempDict allValues]) {
[self getDataFromTwitterUserAPIandArchiveFor:person.handle];
}
Could you set it up differently and call the [getData... method every time the timer fires? You could keep your dictionary keys in an array and pop the next key each time the timer fired.
I think the NSTimer is designed to not block the main thread whereas the for-loop definitely blocks the thread.
As in this related question Using NSTimer in a Loop, you might consider NSRunLoop.

indexpath as parameters

I got an table which is filled with VM's and i have 2 variable of the datatype NSIndexPath called:
selectedindexpath(the row the user clicks on) and
selectedindexpathFortheVMtoTurnOn(so it knows which row to reload when the VM went on);
which is both made in the .h as #paramters(retain) ..
i got a function that turns on the VM's and a function that CHECKS every 1 sec with a NSTimer if the guest is finally on then it reloads the row of selectedindexpathFortheVMtoTurnOn
im doing the same for OFF/REBOOT but i have got a problem with this.. im not able to request an action for more then 1 VM.. because it is overwriting the selectedindexpathFortheVMtoTurnOn value with the last row which i sent an action to and by doing so the table responds wierd and the app crashes..
so thats why i want to give the indexpath.row value as parameters with the NSTimer to the function that checks every 1 sec i have tried a few things but none have worked.. below the code of how i am giving the parameters
timertocallguest=[NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(gettheguestyouaskedforTOTURNON:)
userInfo:selectedindexpathFortheVMtoTurnOn
repeats:YES];
and the function:
-(void)gettheguestyouaskedforTOTURNON:(NSIndexPath *)therow
and when i try to do a NSLog("%d",therow.row); it crashes...
and with NSLog("%d",therow); i get a whole diffrent value of the selectedindexpathFortheVMtoTurnOn that it used to had..
what am i doing wrong.?
sorry if its a wall of text. but i realy need to fix this problem as this is getting released as BETA nextweek in the appstore for the company where my traineeperiode is.
ty in advance.
EDIT:
i will try to show it with pictures this time.
At first im at the view with VM's
http://imageshack.us/photo/my-images/194/schermafbeelding2011052l.png/
after that i can press on the button with the arrow and i get to choose what i want to do.
http://imageshack.us/photo/my-images/822/schermafbeelding2011052r.png/
an activity indicator appears and it stops when the action is done.(which has to do with the NStimer that checks every 1 sec)
http://imageshack.us/photo/my-images/828/schermafbeelding2011052y.png/
http://imageshack.us/photo/my-images/811/schermafbeelding2011052t.png/
but when i try to do an action at 2 or more VM's the activity indicator on the last row i selected spins *x faster(depends on how manny actions i send.. 2 actions means it spins 2 times faster..(so weird)
.. i hope this is enough for you to understand what i mean now =)
The method triggered by an NSTimer object always has the timer as the argument. You can get the row like this.
-(void)gettheguestyouaskedforTOTURNON:(NSTimer *)timer {
NSIndexPath *indexPath = (NSIndexPath*)[timer userInfo];
NSLog(#"%d", indexPath.row);
}