I have an array of lattitudes and longitudes in my array,
NSArray *anArrayOfFloatObjects = [NSArray arrayWithObjects:
[NSNumber numberWithDouble:pinLocation1.latitude],
[NSNumber numberWithDouble:pinLocation1.longitude],
[NSNumber numberWithDouble:pinLocation2.latitude],
[NSNumber numberWithDouble:pinLocation2.longitude],
[NSNumber numberWithDouble:pinLocation3.latitude],
[NSNumber numberWithDouble:pinLocation3.longitude],
nil];
What I want to do is use a switch statement to go through the array (i.e. objectAtIndex..)
switch (self.anArrayOfFloatObjects objectAtIndex:) {
case :0
//switch the pin color to red
break;
case :2
//switch pin color to green
break;
default:
break;
}
This obviously doesnt work. Does anyone know any other way?
I believe what you are looking for is
[anArrayOfFloatObjects indexOfObject:number]
Maybe this code will help:
NSArray *anArrayOfFloatObjects; //Your array
for (NSNumber *number in anArrayOfFloatObjects) {
switch ([anArrayOfFloatObjects indexOfObject:number]) {
case :0
//switch the pin color to red
break;
case :2
//switch pin color to green
break;
default:
break;
}
}
EDIT:
Following #MikeS comment you can do something like this:
for (int index = 0; index < [anArrayOfFloatObjects count]; index++) {
switch (index) {
case :0
//switch the pin color to red
break;
case :2
//switch pin color to green
break;
default:
break;
}
}
Avoiding the need of calling [anArrayOfFloatObjects indexOfObject:number]
try fast enumeration
for(id item in anArrayOfFloatObjects){
NSLog(#"%#", item);
}
You can also look into NSArray's enumerateObjectsUsingBlock.
[yourArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"Index: %ld - Object: %#", idx, obj);
}];
Related
In Swift it is possible to check a tuple like,
switch(type1, type2) {
case (1, 1):
functionNormal()
case (1, 2):
functionUncommon()
case (1, 3):
functionRare()
...
}
Is it possible to check tuple like multiple values in Objective-C Switch case? Any way around?
There could be various approaches, depending on exactly what your type1 and type2 data might be.
However, here is a basic example:
NSInteger i = 1;
NSInteger j = 2;
switch (i) {
case 1:
switch (j) {
case 1:
[self functionNormal];
break;
case 2:
[self functionUncommon];
break;
case 3:
[self functionRare];
break;
default:
NSLog(#"first value: 1 ... missing case for second value: for %ld", (long)j);
break;
}
break;
case 2:
switch (j) {
case 1:
[self secondFunctionNormal];
break;
case 2:
[self secondFunctionUncommon];
break;
case 3:
[self secondFunctionRare];
break;
default:
NSLog(#"first value: 2 ... missing case for second value: %ld", (long)j);
break;
}
break;
default:
NSLog(#"missing first case for first value: %ld", (long)i);
break;
}
This is rather inefficient, of course, but maybe it can get you on your way.
Edit
Again, it will depend on your data, but another approach more closely resembling your Swift example:
NSInteger i = 1;
NSInteger j = 2;
NSInteger ij = i * 1000 + j;
switch (ij) {
case 1001:
[self functionNormal];
break;
case 1002:
[self functionUncommon];
break;
case 1003:
[self functionRare];
break;
case 2001:
[self secondFunctionNormal];
break;
case 2002:
[self secondFunctionUncommon];
break;
case 2003:
[self secondFunctionRare];
break;
default:
NSLog(#"case was something else: %ld", (long)ij);
break;
}
i made a random for A-Z. The random letter is shown in a label. everything works fine. But the letter should not repeat till every letter from A-Z is called.
I´am new in xcode an need a litte help.
heres my code in the .m file.
NSString *letters = #"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-(NSString *) randomStringWithLength:(int) len {
NSMutableString *randomString = [NSMutableString stringWithCapacity: len];
for (int i=26; i<len; i++) {
[randomString appendFormat: #"%C", [letters characterAtIndex: arc4random() % [letters length]]]; buchstabeAusgabe.text = randomString;
}
return randomString;}
-(void)neuerGenerator {
int text = rand() %26;
switch (text) {
case 0:
buchstabeAusgabe.text =#"A";
break;
case 1:
buchstabeAusgabe.text =#"B";
break;
case 2:
buchstabeAusgabe.text =#"C";
break;
case 3:
buchstabeAusgabe.text =#"D";
break;
case 4:
buchstabeAusgabe.text =#"E";
break;
case 5:
buchstabeAusgabe.text =#"F";
break;
case 6:
buchstabeAusgabe.text =#"G";
break;
case 7:
buchstabeAusgabe.text =#"H";
break;
case 8:
buchstabeAusgabe.text =#"I";
break;
case 9:
buchstabeAusgabe.text =#"J";
break;
case 10:
buchstabeAusgabe.text =#"K";
break;
case 11:
buchstabeAusgabe.text =#"L";
break;
case 12:
buchstabeAusgabe.text =#"M";
break;
case 13:
buchstabeAusgabe.text =#"N";
break;
case 14:
buchstabeAusgabe.text =#"O";
break;
case 15:
buchstabeAusgabe.text =#"P";
break;
case 16:
buchstabeAusgabe.text =#"Q";
break;
case 17:
buchstabeAusgabe.text =#"R";
break;
case 18:
buchstabeAusgabe.text =#"S";
break;
case 19:
buchstabeAusgabe.text =#"T";
break;
case 20:
buchstabeAusgabe.text =#"U";
break;
case 21:
buchstabeAusgabe.text =#"V";
break;
case 22:
buchstabeAusgabe.text =#"W";
break;
case 23:
buchstabeAusgabe.text =#"X";
break;
case 24:
buchstabeAusgabe.text =#"Y";
break;
case 25:
buchstabeAusgabe.text =#"Z";
break;
default:
break;
}}
instead of the switch, perhaps store the alphabet in an NSMutableArray. When a letter is taken, remove it from the array. Instead of %26 do %[array count]. To look up the item in array, use [array objectAtIndex:index] where index is the random number.
I am not on XCode at the moment, but I'll try to write out the full code:
- (NSString *) randomStringWithLength:(int) len andAlphabet: (NSString *) alphabet {
NSMutableArray *alphabetArrayMut = [[self arrayFromString: alphabet] mutableCopy];
NSMutableString *resultString = [NSMutableString stringWithString:#""];
while([alphabetArrayMut count]&&[resultString length]<len){
int index = rand() % [alphabetArrayMut count];
NSString *charToAdd = [alphabetArrayMut objectAtIndex:index];
[resultString appendString:charToAdd];
[alphabetArrayMut removeObjectAtIndex:index];
}
return [resultString copy];
}
- (NSArray *) arrayFromString: (NSString *) string{
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[string length]];
for (int i=0; i < [string length]; i++) {
NSString *ichar = [NSString stringWithFormat:#"%c", [string characterAtIndex:i]];
[characters addObject:ichar];
}
return [characters copy];
}
Note that it is probably a lot easier to use recursion. Unfortunately, I am not on my mac at the moment, so I can't test it:
- (NSString *) randomStringWithLength:(int) len andAlphabet: (NSString *) alphabet {
if(len <= 0 || ![alphabet count]){ // base case
return #"";
}
int index = rand() % [alphabet count];
NSString *chosenLetter = [alphabet substringWithRange:NSMakeRange(index, 1)];
NSString *newAlphabet = [alphabet stringByReplacingCharactersInRange:NSMakeRange(index, 1) withString:#""];
NSString *resultString = [NSString stringWithFormat:#"%#%#",chosenLetter,[self randomStringWithLength:len-1,newAlphabet];
return resultString;
}
Lots of different ways to do this. My suggestion would be to use a mutable array:
Add this statement to your .h file:
NSMutableArray *randomLetters;
And then add this method to your .m file:
(Code edited to clean up a ton of typos and minor mistakes)
- (NSString *) randomLetter;
{
if (randomLetters == nil)
randomLetters = [NSMutableArray arrayWithCapacity: 26];
if (randomLetters.count == 0)
{
for (unichar aChar = 'A'; aChar <= 'Z'; aChar++)
{
[randomLetters addObject: [NSString stringWithCharacters: &aChar length: 1]];
}
}
NSUInteger randomIndex = arc4random_uniform((u_int32_t)randomLetters.count);
NSString *result = randomLetters[randomIndex];
[randomLetters removeObjectAtIndex: randomIndex];
return result;
}
(Disclaimer: I typed that code out in the SO editor. I haven't tried to compile it, so it may contain minor typos.)
The method randomLetter will give you a single, non-repeating random letter every time you call it, until the array of remaining random letters is empty. At that point it will repopulate the array with the full alphabet and start over.
The random number generator arc4random_uniform() gives much better results that rand(), and doesn't suffer from "modulo bias" (link) like the expression rand()%range does.
Note that it is possible for the above method to give you the last random letter (an "a", for example") then on the next call, repopulate the array, and give you another "a" from the newly populated array. However, the odds of that happening are only 1 in 26.
You could tweak the above code so it remembers the last character it gives you and doesn't give you that same character twice in a row if that's important.
You could pretty easily change it slightly so that it would give you letters one at a time until it's empty and then return nil, and then write a separate method to fill it. That way you could get exactly 26 non-repeating characters and know when you about to repeat with another set of 26 characters.
because c string is terminal by '\0', we need 27 bytes.
NSString *alp = #"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char cstr[27];
[alp getCString:cstr maxLength:27 encoding:NSUTF8StringEncoding];
// do i from 25 to 0. to 1 is ok, also
for (int i = alp.length - 1; i >= 0; --i) {
int mark = arc4random_uniform(i);
char temp = cstr[i];
cstr[i] = cstr[mark];
cstr[mark] = temp;
}
NSString *str = [NSString stringWithUTF8String:cstr];
NSLog(#"%#", str);
Given these methods:
- (NSString *)stringOfRandomLettersWithLength:(NSUInteger)length {
if (length > 26) {
return nil;
}
NSMutableString *stringOfRandomLetters = [NSMutableString stringWithCapacity:length];
NSArray *letters = #[ #"A", #"B", #"C", #"D", #"E", #"F", #"G", #"H", #"I", #"J", #"K", #"L", #"M", #"N", #"O", #"P", #"Q", #"R", #"S", #"T", #"U", #"V", #"W", #"X", #"Y", #"Z" ];
NSMutableArray *unusedLetters = [letters mutableCopy];
NSString *randomLetter;
for (int i=0; i<length; i++) {
randomLetter = [self randomItemFromArray:unusedLetters];
[unusedLetters removeObject:randomLetter];
[stringOfRandomLetters appendString:randomLetter];
}
return stringOfRandomLetters;
}
- (NSString *)randomItemFromArray:(NSArray *)items {
if (items.count < 1) {
return nil;
}
return items[ arc4random_uniform((u_int32_t)items.count) ];
}
You could create a string of random, distinct letters like this:
NSString *label = [self stringOfRandomLettersWithLength:26];
NSLog(#"label= %#", label);
In the console you'd see something like this:
label= YGRHCXTFDZLKNPAIEOJSUQWVMB
I am implementing a scatter graph in core plot and one of the data source methods is returning a huge number. Here is the method:
- (NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot {
return [self.values count];
}
- (NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
switch (fieldEnum) {
case CPTScatterPlotFieldX:
if (index < [self.practices count]) {
return [NSNumber numberWithUnsignedInteger:index];
}
break;
case CPTScatterPlotFieldY:
if ([plot.identifier isEqual:#"Practices"]) {
return self.values[index];
}
break;
}
return [NSDecimalNumber zero];
}
Here is the population of self.values:
NSMutableArray *value = [[NSMutableArray alloc] initWithCapacity:200];
for (int i = 200; i > 0; i--) {
NSInteger randomNumber = arc4random() % 200;
[value addObject:[NSNumber numberWithInt:randomNumber]];
}
NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:#"self" ascending:NO];
[value sortUsingDescriptors:[NSArray arrayWithObject:highestToLowest]];
self.values = [value copy];
The graph is crashing when it calls: return self.values[index];. When I try to debug the application I am finding that the index passed in is very large.
Here is a picture of that variable. It's the one called index:
I am trying to figure out why this number is so large. Everything seems to be similar to other graphs I have implemented. However this seems to be throwing in a large number.
I have managed to find a work around to get this to work. My original code did not have a check in CPTScatterPlotFieldY to see if index < [self.values count].
switch (fieldEnum) {
case CPTScatterPlotFieldX:
if (index < [self.values count]) {
return [NSNumber numberWithUnsignedInteger:index];
}
break;
case CPTScatterPlotFieldY:
if ([plot.identifier isEqual:#"gpPractices"] && index < [self.values count]) {
return self.values[index];
}
break;
}
return [NSDecimalNumber zero];
By adding this check it only tries to access the self.values array if the index is less than the number of objects in the array.
i need to send in one package two float numbers. I use CocoaOSC project https://github.com/danieldickison/CocoaOSC
how i call function to send:
[delegate sendPacket:#"/ShotHappends" value:[NSString stringWithFormat:#"%.3f %.3f", myXRound, myYRound] type:2];
my function
- (void)sendPacket:(NSString*)address value:(NSString*)sendValue type:(int)type
{
defaults = [NSUserDefaults standardUserDefaults];
remoteHost = [defaults stringForKey:#"host"];
remotePort = [defaults stringForKey:#"port"];
NSLog(#"Value: %#", sendValue);
OSCMutableMessage *message = [[OSCMutableMessage alloc] init];
message.address = address;
sendType = type;
switch (sendType)
{
case 0: [message addString:sendValue]; break;
case 1: [message addInt:[sendValue intValue]]; break;
case 2: [message addFloat:[sendValue floatValue]]; break;
case 3: [message addBlob:[sendValue dataUsingEncoding:NSUTF8StringEncoding]]; break;
case 4: [message addTimeTag:[NSDate date]]; break;
case 5: [message addBool:YES]; break;
case 6: [message addBool:NO]; break;
case 7: [message addImpulse]; break;
case 8: [message addNull]; break;
}
[connection sendPacket:message toHost:remoteHost port:[remotePort intValue]];
}
so as you see i create a string and say in my function what is in these string, if i say that string #"0,22 0,45" is float my server will get only first number, so how can i send two floats to my server? Thank you.
I haven't tested this, or even read the API, but I would imagine you would have to create a version of your method that accepts arrays of type/values:
- (void)sendPacket:(NSString*)address
values:(NSArray*)values
types:(NSArray*)types
{
NSAssert([values count] == [types count], #"Values/types array are different sizes!");
defaults = [NSUserDefaults standardUserDefaults];
remoteHost = [defaults stringForKey:#"host"];
remotePort = [defaults stringForKey:#"port"];
OSCMutableMessage *message = [[OSCMutableMessage alloc] init];
message.address = address;
for (NSUInteger i = 0; i < [values count]; i++)
{
int sendType = [[types objectAtIndex:i] intValue];
id sendValue = [values objectAtIndex:i];
switch (sendType)
{
case 0: [message addString:sendValue]; break;
case 1: [message addInt:[sendValue intValue]]; break;
case 2: [message addFloat:[sendValue floatValue]]; break;
case 3: [message addBlob:[sendValue dataUsingEncoding:NSUTF8StringEncoding]]; break;
case 4: [message addTimeTag:[NSDate date]]; break;
case 5: [message addBool:YES]; break;
case 6: [message addBool:NO]; break;
case 7: [message addImpulse]; break;
case 8: [message addNull]; break;
}
}
[connection sendPacket:message toHost:remoteHost port:[remotePort intValue]];
}
Note: as you are passing the types (int) in an Objective-C collection class, they must be wrapped in NSNumber objects:
[delegate sendPacket:#"/ShotHappends"
values:#[[NSString stringWithFormat:#"%.3f", myXRound],
[NSString stringWithFormat:#"%.3f", myYRound]
]
types:#[ #(2), #(2) ]
];
Note 2: An improvement to your method would be to pass strings as NSString, numbers/bools as NSNumber and data as NSData rather than using NSString all the time. Up to you, though.
I have a little coding problem at the moment. I have a picker with 7 different options, currently for testing purposes I have a label that will display the chosen value of the picker.
The problem that I am having is that my label is only displaying whole numbers, not displaying the entire decimal number, can someone please help me so that I can obtain the full value of the chosen item in the picker?
Here is my code :
// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [tempList count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [tempList objectAtIndex:row];
}
- (void)pickerView:(UIPickerView *)pickerView
didSelectRow:(NSInteger)row
inComponent:(NSInteger)component {
CGFloat chosenValue;
switch (row) {
case 0:
chosenValue = 0.0000373;
break;
case 1:
chosenValue = 0.0000273;
break;
case 2:
chosenValue = 0.0000233;
break;
case 3:
chosenValue = 0.0000204;
break;
case 4:
chosenValue = 0.0000179;
break;
case 5:
chosenValue = 0.0000169;
break;
case 6:
chosenValue = 0.0000142;
break;
default:
chosenValue = 0;
break;
}
NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
self.testLabel.text = [formatter stringFromNumber:#(chosenValue)];
}
You need to specify the precision:
self.textLabel.text = [NSString stringWithFormat:#"%.7f", chosenValue];
The %f format specifier defaults to 5 decimal places.
And you probably need to change chosenValue to double to get enough significant digits.
Better yet, since you are using an NSNumberFormatter, set the number of decimals:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
formatter.minimumFractionDigits = 7;
Why did you not use NSString stringWithFormat method?
self.textLabel.text = [NSString stringWithFormat:#"%.10f", chosenValue];
Try this :
self.testLabel.text = [NSString stringWithFormat:#"%.10f",chosenValue];
instead of:
self.testLabel.text = [formatter stringFromNumber:#(chosenValue)];