I am having a mac app in which I want to update my label after some seconds.
I have used the following code with NSTimer.
[NSTimer scheduledTimerWithTimeInterval:1.0/30 target:self selector:#selector(count:) userInfo:nil repeats:YES];
float k = 0.0;
if (k >= 958.36)
{
[timer invalidate];
return;
}
NSString* string = [NSString stringWithFormat:#"%.2f", k];
NSLog(#"%#",string);
[lbl setStringValue:string];
k++;
When I am using this code the value increases like below.
1.00
2.00
3.00
4.00
5.00
It only updates the integer values but not the decimal numbers. It should work like 1.10,1.11,1.12...
I know there are lots of questions on this and solutions but didn't work for me.
Can anyone help me on this?
Thanks...
The use of k++ is the issue as that is incrementing k by 1.0.
Increment using a different value, for example:
k += 0.1f;
You're printing k, which you are increasing by 1 every time the timer fires. If you want to print 1.10,1.11,1.12 et.c. you need to use:
NSString* string = [NSString stringWithFormat:#"1.%2f", k+10];
if (k >= 958.36)
{
[timer invalidate];
return;
}
NSString* string = [NSString stringWithFormat:#"%.2f", k];
NSLog(#"%#",string);
[lbl setStringValue:string];
k += 0.01f;
This question already has answers here:
iOS Format String into minutes and seconds
(7 answers)
Closed 8 years ago.
I am trying to get a timer to show the counter like this "00:00:00". Here is my current code. I have been trying to get it to work using the stringWithFormat which should be easy but I guess I will have to set up the formats separately. Do you guys have any idea on how to do this?
- (void)TimerCount {
CountNumber = CountNumber + 1;
TimerDisplay.text = [NSString stringWithFormat:#"Hour: %0*i", length, hour];
}
- (void)timerCount {
{
CountNumber = CountNumber + 1;
NSInteger seconds = CountNumber % 60;
NSInteger minutes = (CountNumber / 60) % 60;
NSInteger hours = (CountNumber / 3600);
TimerDisplay.text = [NSString stringWithFormat:#"%i:%02i:%02i", hours, minutes, seconds];
}
Try the above code.
And configure this method to be fired every second.
In viewDidLoad
NSTimer *counterTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerCount)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer: counterTimer forMode:NSRunLoopCommonModes];
And keep the counterTimer as an iVar to keep it alive until the VC is dealloced, if you are using ARC.
- (void)TimerCount
{
CountNumber++;
NSString *time = [[NSString alloc] init];
NSUInteger seconds = CountNumber;
NSUInteger minutes = 0;
NSUInteger hours = 0;
if (seconds > 59) {
seconds -= 60;
minutes++;
if (seconds < 10) {
time = [NSString stringWithFormat:#":0%i",seconds];
} else time = [NSString stringWithFormat:#":%i",seconds];
}
if (minutes > 59) {
minutes -= 60;
hours++;
if (minutes < 10) {
time = [NSString stringWithFormat:#":0%i%#",minutes,time];
} else time = [NSString stringWithFormat:#":%i%#",minutes,time];
}
if (hours < 10) {
time = [NSString stringWithFormat:#"0%i%#",hours,time];
} else time = [NSString stringWithFormat:#"%i%#",hours,time];
}
NSString *time is the time.
Also NSTimer to call this method every second:
NSTimer *counterTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerCount)
userInfo:nil
repeats:YES];
I want to update text for label frequently but it seems not working.
for (int i = 0; i <100; i++)
{
mylabel.text =[NSString stringWithFormat:#"%d", i];
}
Does anyone suggest for me an idea ? I thought. Maybe, we should update text label in multiple threads.
Watch is best example hope it will help you....
int second,minute; //set second = 0 and minute = 0
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateCounter:) userInfo:nil repeats:YES];
- (void)updateCounter:(NSTimer *)theTimer {
second++;
if(second < 60)
{
if (second < 10)
{
timerLbl.text = [NSString stringWithFormat:#"00:0%d", second];
}
else
{
timerLbl.text = [NSString stringWithFormat:#"00:%d",second];
}
}
else
{
minute = second / 60;
int sec = second % 60;
if (minute < 10 && sec < 10)
{
timerLbl.text = [NSString stringWithFormat:#"0%d:0%d", minute, sec];
}
if(minute < 10 && sec >= 10)
{
timerLbl.text = [NSString stringWithFormat:#"0%d:%d", minute, sec];
}
if (minute >= 10 && sec < 10)
{
timerLbl.text = [NSString stringWithFormat:#"%d:0%d", minute, sec];
}
if(minute >= 10 && sec >= 10)
{
timerLbl.text = [NSString stringWithFormat:#"%d:%d", minute, sec];
}
}
}
Add below code in viewDidLoad
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.5f
target:self
selector:#selector(showTime)
userInfo:NULL
repeats:YES];
- (void)showTime
{
NSDate *now=[NSDate date];
NSDateFormatter *dateFormatter=[NSDateFormatter new];
[dateFormatter setDateFormat:#"HH:mm:ss"];
timeLabel.text=[dateFormatter stringFromDate:now];
}
Hope this answer will help you....
use NSTimer for the regular interval and call the method where the lable is printed let suppose
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(targetMethod:)
userInfo:nil
repeats:Yes];
in the target method print the label on text
-(void)targetMethod:(NSTimer *)timer{
NSDate* date = [NSDate date];
NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#" HH:MM:SS"];
NSString* str = [formatter stringFromDate:date];
label.text = str;
}
try this it will work surely
Ok, I basically need to find a way to better manage 100 NSMutableArrays of data.
Like, (I haven't actually done this) :
NSMutableArray *array1;
NSMutableArray *array2;
NSMutableArray *array3;
//etc..
I need something that has multiple facets, like:
NSMutableCombinationArray *theMassiveArray;
[theMassiveArray addObject:theObject forArray:0 atIndex:0];
In the end I want to do something like this:
//in applicationdidfinishlaunching
loopCount = 0;
- (void) frameTimer:(NSTimer*)timer { //called every second
startingValue = 0;
for (int i = 1; i <= 100; i++)
{
NSString *dmxValues = [NSString stringWithFormat: #"%#,%#,%#,%#,%#", [DMXChannelArray objectAtIndex:startingValue], [DMXChannelArray objectAtIndex:startingValue+1], [DMXChannelArray objectAtIndex:startingValue+2], [DMXChannelArray objectAtIndex:startingValue+3], [DMXChannelArray objectAtIndex:startingValue+4]];
[theMassiveArray addObject:dmxValues forArray:i-1 atIndex:loopCount];
startingValue = startingValue + 5;
}
loopCount = loopCount + 1;
}
//NOTE DMXChannelArray is updated in another class with current DMX values from a controller.
So there are 512 channels of DMX, and each array needs to hold 5 channels. It's a recording app that basically stores 500 DMX channel values at a resolution of one time a second.
How can I do this? What's the best way to do this? I obviously want to avoid writing 100 NSMutableArrays and doing this all manually.
For reference, when recording is over, the user selects how many groups (of 5 channels) he wants to export, then depending on that number, another for loop will go through the NSMutableCombinationArray and export the final arrays.
Write a wrapper class:
#interface MultiDimensionalMutableArray : NSObject
- (void)insertObject:(id)obj atIndex:(NSUInteger)idx intoArrayAtIndex:(NSUInteger)arrIdx;
- (id)objectAtIndex:(NSUInteger)idx inArrayAtIndex:(NSUInteger)arrIdx;
#end
#implementation MultiDimensionalMutableArray
{
NSMutableArray * arrays;
}
- (id)init
{
// init boilerplate
arrays = [NSMutableArray arrayWithCapacity:100];
for( int i = 0; i < 100; i++ ){
[arrays addObject:[NSMutableArray array]];
}
return self;
}
- (void)insertObject:(id)obj atIndex:(NSUInteger)idx intoArrayAtIndex:(NSUInteger)arrIdx
{
//TODO: Include appropriate bounds checking
NSMutableArray * innerArray = [arrays objectAtIndex:arrIdx];
[innerArray insertObject:obj atIndex:idx];
}
- (id)objectAtIndex:(NSUInteger)idx inArrayAtIndex:(NSUInteger)arrIdx
{
return [[arrays objectAtIndex:arrIdx] objectAtIndex:idx];
}
#end
Here's what you should do
NSMutableArray *massiveArray = [[NSMutableArray alloc] init];
for(int i=0; i<500; i+=5) {
NSDictionary *dataDict = [[NSDictionary alloc] initWithObjectsAndKeys:[DMXChannelArray objectAtIndex:i], #"Key1", [DMXChannelArray objectAtIndex:i+1], #"Key2", [DMXChannelArray objectAtIndex:i+2], #"Key3", [DMXChannelArray objectAtIndex:i+3], #"Key4", [DMXChannelArray objectAtIndex:i+4], #"Key5", nil];
[massiveArray addObject:dataDict];
}
So finally the massiveArray contains 100 dictionaries, and for instance, to access the 2nd value of 45th dictionary, you do this :
NSString *value = [[massiveArray objectAtIndex:44] objectForKey:#"Key2"];
Hope this helps
Well
NSMutableDictionary *dict = [NSMutableDictionary alloc] initWithCapacity:100];
for(int i=1; i<=100; i++){
NSString *dmxValues = [NSString stringWithFormat: #"%#,%#,%#,%#,%#", [DMXChannelArray objectAtIndex:startingValue], [DMXChannelArray objectAtIndex:startingValue+1], [DMXChannelArray objectAtIndex:startingValue+2], [DMXChannelArray objectAtIndex:startingValue+3], [DMXChannelArray objectAtIndex:startingValue+4]];
[dict setObject:[NSArray arrayWithObject:dmxValues] forKey:[NSNumber numberWithInt:(i-1)];
}
To retrieve your values
[dic objectForkey:[NSNumber numberWithInt:array_index][array_element_index];
I need to reverse my NSArray.
As an example:
[1,2,3,4,5] must become: [5,4,3,2,1]
What is the best way to achieve this?
There is a much easier solution, if you take advantage of the built-in reverseObjectEnumerator method on NSArray, and the allObjects method of NSEnumerator:
NSArray* reversedArray = [[startArray reverseObjectEnumerator] allObjects];
allObjects is documented as returning an array with the objects that have not yet been traversed with nextObject, in order:
This array contains all the remaining objects of the enumerator in enumerated order.
For obtaining a reversed copy of an array, look at danielpunkass' solution using reverseObjectEnumerator.
For reversing a mutable array, you can add the following category to your code:
#implementation NSMutableArray (Reverse)
- (void)reverse {
if ([self count] <= 1)
return;
NSUInteger i = 0;
NSUInteger j = [self count] - 1;
while (i < j) {
[self exchangeObjectAtIndex:i
withObjectAtIndex:j];
i++;
j--;
}
}
#end
Some benchmarks
1. reverseObjectEnumerator allObjects
This is the fastest method:
NSArray *anArray = #[#"aa", #"ab", #"ac", #"ad", #"ae", #"af", #"ag",
#"ah", #"ai", #"aj", #"ak", #"al", #"am", #"an", #"ao", #"ap", #"aq", #"ar", #"as", #"at",
#"au", #"av", #"aw", #"ax", #"ay", #"az", #"ba", #"bb", #"bc", #"bd", #"bf", #"bg", #"bh",
#"bi", #"bj", #"bk", #"bl", #"bm", #"bn", #"bo", #"bp", #"bq", #"br", #"bs", #"bt", #"bu",
#"bv", #"bw", #"bx", #"by", #"bz", #"ca", #"cb", #"cc", #"cd", #"ce", #"cf", #"cg", #"ch",
#"ci", #"cj", #"ck", #"cl", #"cm", #"cn", #"co", #"cp", #"cq", #"cr", #"cs", #"ct", #"cu",
#"cv", #"cw", #"cx", #"cy", #"cz"];
NSDate *methodStart = [NSDate date];
NSArray *reversed = [[anArray reverseObjectEnumerator] allObjects];
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(#"executionTime = %f", executionTime);
Result: executionTime = 0.000026
2. Iterating over an reverseObjectEnumerator
This is between 1.5x and 2.5x slower:
NSDate *methodStart = [NSDate date];
NSMutableArray *array = [NSMutableArray arrayWithCapacity:[anArray count]];
NSEnumerator *enumerator = [anArray reverseObjectEnumerator];
for (id element in enumerator) {
[array addObject:element];
}
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(#"executionTime = %f", executionTime);
Result: executionTime = 0.000071
3. sortedArrayUsingComparator
This is between 30x and 40x slower (no surprises here):
NSDate *methodStart = [NSDate date];
NSArray *reversed = [anArray sortedArrayUsingComparator: ^(id obj1, id obj2) {
return [anArray indexOfObject:obj1] < [anArray indexOfObject:obj2] ? NSOrderedDescending : NSOrderedAscending;
}];
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(#"executionTime = %f", executionTime);
Result: executionTime = 0.001100
So [[anArray reverseObjectEnumerator] allObjects] is the clear winner when it comes to speed and ease.
DasBoot has the right approach, but there are a few mistakes in his code. Here's a completely generic code snippet that will reverse any NSMutableArray in place:
/* Algorithm: swap the object N elements from the top with the object N
* elements from the bottom. Integer division will wrap down, leaving
* the middle element untouched if count is odd.
*/
for(int i = 0; i < [array count] / 2; i++) {
int j = [array count] - i - 1;
[array exchangeObjectAtIndex:i withObjectAtIndex:j];
}
You can wrap that in a C function, or for bonus points, use categories to add it to NSMutableArray. (In that case, 'array' would become 'self'.) You can also optimize it by assigning [array count] to a variable before the loop and using that variable, if you desire.
If you only have a regular NSArray, there's no way to reverse it in place, because NSArrays cannot be modified. But you can make a reversed copy:
NSMutableArray * copy = [NSMutableArray arrayWithCapacity:[array count]];
for(int i = 0; i < [array count]; i++) {
[copy addObject:[array objectAtIndex:[array count] - i - 1]];
}
Or use this little trick to do it in one line:
NSArray * copy = [[array reverseObjectEnumerator] allObjects];
If you just want to loop over an array backwards, you can use a for/in loop with [array reverseObjectEnumerator], but it's likely a bit more efficient to use -enumerateObjectsWithOptions:usingBlock::
[array enumerateObjectsWithOptions:NSEnumerationReverse
usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
// This is your loop body. Use the object in obj here.
// If you need the index, it's in idx.
// (This is the best feature of this method, IMHO.)
// Instead of using 'continue', use 'return'.
// Instead of using 'break', set '*stop = YES' and then 'return'.
// Making the surrounding method/block return is tricky and probably
// requires a '__block' variable.
// (This is the worst feature of this method, IMHO.)
}];
(Note: Substantially updated in 2014 with five more years of Foundation experience, a new Objective-C feature or two, and a couple tips from the comments.)
After reviewing the other's answers above and finding Matt Gallagher's discussion here
I propose this:
NSMutableArray * reverseArray = [NSMutableArray arrayWithCapacity:[myArray count]];
for (id element in [myArray reverseObjectEnumerator]) {
[reverseArray addObject:element];
}
As Matt observes:
In the above case, you may wonder if -[NSArray reverseObjectEnumerator] would be run on every iteration of the loop — potentially slowing down the code. <...>
Shortly thereafter, he answers thus:
<...> The "collection" expression is only evaluated once, when the for loop begins. This is the best case, since you can safely put an expensive function in the "collection" expression without impacting upon the per-iteration performance of the loop.
Georg Schölly's categories are very nice. However, for NSMutableArray, using NSUIntegers for the indices results in a crash when the array is empty. The correct code is:
#implementation NSMutableArray (Reverse)
- (void)reverse {
NSInteger i = 0;
NSInteger j = [self count] - 1;
while (i < j) {
[self exchangeObjectAtIndex:i
withObjectAtIndex:j];
i++;
j--;
}
}
#end
The most efficient way to enumerate an array in reverse:
Use enumerateObjectsWithOptions:NSEnumerationReverse usingBlock. Using #JohannesFahrenkrug's benchmark above, this completed 8x quicker than [[array reverseObjectEnumerator] allObjects];:
NSDate *methodStart = [NSDate date];
[anArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
//
}];
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(#"executionTime = %f", executionTime);
NSMutableArray *objMyObject = [NSMutableArray arrayWithArray:[self reverseArray:objArrayToBeReversed]];
// Function reverseArray
-(NSArray *) reverseArray : (NSArray *) myArray {
return [[myArray reverseObjectEnumerator] allObjects];
}
Reverse array and looping through it:
[[[startArray reverseObjectEnumerator] allObjects] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
...
}];
To update this, in Swift it can be done easily with:
array.reverse()
As for me, have you considered how the array was populated in the first place? I was in the process of adding MANY objects to an array, and decided to insert each one at the beginning, pushing any existing objects up by one. Requires a mutable array, in this case.
NSMutableArray *myMutableArray = [[NSMutableArray alloc] initWithCapacity:1];
[myMutableArray insertObject:aNewObject atIndex:0];
Or the Scala-way:
-(NSArray *)reverse
{
if ( self.count < 2 )
return self;
else
return [[self.tail reverse] concat:[NSArray arrayWithObject:self.head]];
}
-(id)head
{
return self.firstObject;
}
-(NSArray *)tail
{
if ( self.count > 1 )
return [self subarrayWithRange:NSMakeRange(1, self.count - 1)];
else
return #[];
}
There is a easy way to do it.
NSArray *myArray = #[#"5",#"4",#"3",#"2",#"1"];
NSMutableArray *myNewArray = [[NSMutableArray alloc] init]; //this object is going to be your new array with inverse order.
for(int i=0; i<[myNewArray count]; i++){
[myNewArray insertObject:[myNewArray objectAtIndex:i] atIndex:0];
}
//other way to do it
for(NSString *eachValue in myArray){
[myNewArray insertObject:eachValue atIndex:0];
}
//in both cases your new array will look like this
NSLog(#"myNewArray: %#", myNewArray);
//[#"1",#"2",#"3",#"4",#"5"]
I hope this helps.
I don't know of any built in method.
But, coding by hand is not too difficult. Assuming the elements of the array you are dealing with are NSNumber objects of integer type, and 'arr' is the NSMutableArray that you want to reverse.
int n = [arr count];
for (int i=0; i<n/2; ++i) {
id c = [[arr objectAtIndex:i] retain];
[arr replaceObjectAtIndex:i withObject:[arr objectAtIndex:n-i-1]];
[arr replaceObjectAtIndex:n-i-1 withObject:c];
}
Since you start with a NSArray then you have to create the mutable array first with the contents of the original NSArray ('origArray').
NSMutableArray * arr = [[NSMutableArray alloc] init];
[arr setArray:origArray];
Edit: Fixed n -> n/2 in the loop count and changed NSNumber to the more generic id due to the suggestions in Brent's answer.
If all you want to do is iterate in reverse, try this:
// iterate backwards
nextIndex = (currentIndex == 0) ? [myArray count] - 1 : (currentIndex - 1) % [myArray count];
You can do the [myArrayCount] once and save it to a local variable (I think its expensive), but I’m also guessing that the compiler will pretty much do the same thing with the code as written above.
Swift 3 syntax :
let reversedArray = array.reversed()
Try this:
for (int i = 0; i < [arr count]; i++)
{
NSString *str1 = [arr objectAtIndex:[arr count]-1];
[arr insertObject:str1 atIndex:i];
[arr removeObjectAtIndex:[arr count]-1];
}
Here is a nice macro that will work for either NSMutableArray OR NSArray:
#define reverseArray(__theArray) {\
if ([__theArray isKindOfClass:[NSMutableArray class]]) {\
if ([(NSMutableArray *)__theArray count] > 1) {\
NSUInteger i = 0;\
NSUInteger j = [(NSMutableArray *)__theArray count]-1;\
while (i < j) {\
[(NSMutableArray *)__theArray exchangeObjectAtIndex:i\
withObjectAtIndex:j];\
i++;\
j--;\
}\
}\
} else if ([__theArray isKindOfClass:[NSArray class]]) {\
__theArray = [[NSArray alloc] initWithArray:[[(NSArray *)__theArray reverseObjectEnumerator] allObjects]];\
}\
}
To use just call: reverseArray(myArray);