iOS - CLLocationCoordinate2D/floats/long into a NSDictionary for JSON? - objective-c

I'm looking to convert a simple objectiveC class (not even that at the minute its just some vars in a function) to JSON so that it can be sent and impretated into a java object at the server side.
The Class might have the following fields;
LatLng locationA // a simple POJO with either float or long to represent lat and long.
LatLng locationA
float someFloat
It the minute I am tring to pack everything in to a NSDictonary. Passing the floats in didn't work so I has to convert them to NSStrings. So on the server side they would arive as strings.. which isnt ideal.
CLLocationCoordinate2D location = ... ;
float lat = location.latitude;
float lng = location.longitude;
float aFloat = 0.12434f;
NSString *aFloatstr = [NSString stringWithFormat:#"%f", aFloat];
NSString *latStr = [NSString stringWithFormat:#"%f", lat];
NSString *lngStr = [NSString stringWithFormat:#"%f", lng];
NSDictionary *locationDictionary =
[NSDictionary dictionaryWithObjectsAndKeys:
latStr , #"latitude",
lngStr, #"longitude",
nil];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
locationDictionary, #"locationA",
locationDictionary, #"locationB",
aFloatstr,#"aFloat",
nil];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:&error];
NSString *str = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"%#",str);
Whats the best way do putting CLLocationCoordinate2Ds into an NSDictionary?
How do I add primitative types, long floats ect.. to an NSDictionary?

Instead of putting the latitude and longitude into NSString, you'll have better luck with NSNumber. When NSJSONSerialization comes upon an NSNumber it won't quote the value like it would a string (which is what you want when transmitting numbers, right?).
You'll also want to use double, not float, for latitude and longitude, since that's how they're represented internally. No need to throw away precision.
[NSNumber numberWithDouble:lat]
[NSNumber numberWithDouble:lng]
[NSNumber numberWithFloat:aFloat]
Since instances of NSNumber are objects, you'll be able to store them in NSDictionary no problem.

Use NSNumber instead of strings to wrap the float values, e.g.:
NSDictionary *locationDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:lat] , #"latitude",
[NSNumber numberWithFloat:lng], #"longitude", nil];
That way, NSJSONSerialization will correctly encode them as numeric values.

Structs
Neat way of doing this is to create category for NSValue that understands your struct. In your case it's CLLocationCoordinate2D, but could be any really. Here is snippet from Apple's own documentation explaning usage of NSValue:
// NSValue+Polyhedron.h
typedef struct {
int numFaces;
float radius;
} Polyhedron;
#interface NSValue (Polyhedron)
+ (instancetype)valueWithPolyhedron:(Polyhedron)value;
#property (readonly) Polyhedron polyhedronValue;
#end
// NSValue+Polyhedron.m
#implementation NSValue (Polyhedron)
+ (instancetype)valueWithPolyhedron:(Polyhedron)value
{
return [self valueWithBytes:&value objCType:#encode(Polyhedron)];
}
- (Polyhedron) polyhedronValue
{
Polyhedron value;
[self getValue:&value];
return value;
}
#end
From here usage is quite trivial. To create boxed NSValue:
NSValue *boxedPolyhedron = [NSValue valueWithPolyhedron:yourStruct];
Now you can put boxedPolyhedron whenever NSValue can go, NSArray, NSDictionary, NSSet, and many more, plus al the mutable versions.
To get struct back:
Polyhedron polyStruct = [boxedPolyhedron polyhedronValue];
That's it.
As a bonus, this works for any C type, not only for structs.
floats, longs, etc.
As mentioned above, could do same as above. But, for numbers, you could use NSNumber which is actually a subclass if NSValue with all popular methods already implemented. Here is a list of types you can box by instantiating NSNumber:
+ (NSNumber *)numberWithChar:(char)value;
+ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
+ (NSNumber *)numberWithShort:(short)value;
+ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
+ (NSNumber *)numberWithInt:(int)value;
+ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
+ (NSNumber *)numberWithLong:(long)value;
+ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
+ (NSNumber *)numberWithLongLong:(long long)value;
+ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
+ (NSNumber *)numberWithFloat:(float)value;
+ (NSNumber *)numberWithDouble:(double)value;
+ (NSNumber *)numberWithBool:(BOOL)value;
+ (NSNumber *)numberWithInteger:(NSInteger)value;
+ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value;
In similiar fashion you un-box values using [yourNumber longValue], [yourNumber floatValue], etc.
Hope that helps.

Related

-[__NSArrayI floatValue]: unrecognized selector sent to instance

_data = [NSMutableArray new];
NSNumber *value1 = [NSNumber numberWithFloat: 5.0f];
[_data setValue:value1 forKey:#"foothold"];
NSNumber *value2 = [_data valueForKey:#"foothold"];
NSLog(#"a foothold %f ",[value2 floatValue]);//error here
It's strange, but I don't see my error...
You have a few problems.
_data is mistakenly an NSMutableArray instead of an NSMutableDictionary.
Don't use setValue:forKey: and valueForKey: unless you mean to do KVC.
Use modern syntax (it's easier and it avoid issue #2).
Updated code:
_data = [NSMutableDictionary dictionary];
NSNumber *value1 = #5.0;
_data[#"foothold"] = value1;
NSNumber *value2 = _data[#"foothold"];
NSLog(#"a foothold %f ",[value2 floatValue]);
When you get an "unrecognized selector sent to instance" error, you'll be given the name of the method you're attempting to call (in this case floatValue) as well as the type of object you're calling it on (NSArray here).
So in this case, despite value2 being declared as an NSNumber, the value returned from [_data valueForKey:#"foothold"]; is an NSArray, which does not respond to the floatValue selector.
I'm surprised you weren't given other warnings. Given the syntax, it looks like you should be using an NSMutableDictionary rather than an array. In which case, try this:
NSMutableDictionary *_data = [NSMutableDictionary dictionary];
NSNumber *value1 = #5.0f;
_data[#"foothold"] = value1;
NSNumber *value2 = _data[#"foothold"];
NSLog(#"a foothold %f", [value2 floatValue]);

Objective C syntax help - literals [duplicate]

I was going through the release notes for Xcode 4.4 and noticed this:
LLVM 4.0 Compiler
Xcode now includes the Apple LLVM Compiler version 4.0, including the following newObjective-C language features:
[...]
- Objective-C literals: create literals for NSArray, NSDictionary, and NSNumber, just the same as the literals for NSString
I'm intrigued about this feature. It's not entirely clear to me just how literals for NSString work and how one could use them on NSArray, NSDictionary, and NSNumber.
What are the details?
Copied verbatim from http://cocoaheads.tumblr.com/post/17757846453/objective-c-literals-for-nsdictionary-nsarray-and:
Objective-C literals: one can now create literals for NSArray, NSDictionary, and NSNumber (just like one can create literals for NSString)
NSArray Literals
Previously:
array = [NSArray arrayWithObjects:a, b, c, nil];
Now:
array = #[ a, b, c ];
NSDictionary Literals
Previously:
dict = [NSDictionary dictionaryWithObjects:#[o1, o2, o3]
forKeys:#[k1, k2, k3]];
Now:
dict = #{ k1 : o1, k2 : o2, k3 : o3 };
NSNumber Literals
Previously:
NSNumber *number;
number = [NSNumber numberWithChar:'X'];
number = [NSNumber numberWithInt:12345];
number = [NSNumber numberWithUnsignedLong:12345ul];
number = [NSNumber numberWithLongLong:12345ll];
number = [NSNumber numberWithFloat:123.45f];
number = [NSNumber numberWithDouble:123.45];
number = [NSNumber numberWithBool:YES];
Now:
NSNumber *number;
number = #'X';
number = #12345;
number = #12345ul;
number = #12345ll;
number = #123.45f;
number = #123.45;
number = #YES;
[Edit]
zxoq at http://news.ycombinator.com/item?id=3672744 has added more interesting new subscripting. (Added with literals):
arr[1] === [arr objectAtIndex:1]
dict[#"key"] === [dict objectForKey:#"key"]
[Edit 2]
The new ObjC literals were discussed in multiple WWDC 2012 sessions. I intentionally didn't remove the the filenames and the time of each slide so you can find them for yourself if you feel like. They are essentially the same thing as stated in this post, but there are also a few new things that I'll mention above the images.
Please note that images are all big. Simply drag them into another tab to view them in their original size
[NSNumber numberWithint:42]
[NSNumber numberWithDouble:10.8]
[NSNumber numberWithBool:YES]
[NSNumber numberWithint:6 + x * 2012]
#42
#10.8
#YES
#(6 + x * 2012)
[NSArray arrayWithObjects: a, b, c, nil]
[array objectAtIndex:i]
[NSDictionary dictionaryWithObjectsAndKeys: v1, k1, v2, k2, nil];
[dictionary valueForKey:k]
#[a, b, c]
array[i]
#{k1:v1, k2:v2}
dictionary[k]
This part is new. Expression Literals
When you have an expression (M_PI / 16 for example) you should put it inside parenthesis.
This syntax works for numeral expressions, booleans, finding an index in a (C-) string, boolean values, enum constants, and even character strings!
NSNumber *piOverSixteen = [NSNumber numberWithDouble: (M_PI / 16)];
NSNumber *hexDigit = [NSNumber numberWithChar:"0123456789ABCDEF"[i % 16]];
NSNumber *usesScreenFonts = [NSNumber numberWithBool:[NSLayoutManager usesScreenFonts]];
NSNumber *writingDirection = [NSNumber numberWithInt:NSWritingDirectionLeftToRight];
NSNumber *path = [NSString stringWithUTF8String: getenv("PATH")];
NSNumber *piOverSixteen = #( M_PI / 16 );
NSNumber *hexDigit = #( "0123456789ABCDEF"[i % 16] );
NSNumber *usesScreenFonts = #( [NSLayoutManager usesScreenFonts] );
NSNumber *writingDirection = #( NSWritingDirectionLeftToRight );
NSNumber *path = #( getenv("PATH") );
More about character strings and how/when you can use this literal syntax:
NSString *path = [NSString stringWithUTF8String: getenv("PATH")];
for (NSString *dir in [path componentsSeparatedByString: #":"]) {
// search for a file in dir...
}
NSString *path = #( getenv("PATH") );
for (NSString *dir in [path componentsSeparatedByString: #":"]) {
// search for a file in dir...
}
How array literals work
// when you write this:
array = #[a, b, c ];
// compiler generates:
id objects[] = { a, b, c };
NSUInteger count = sizeof(objects) / sizeof(id);
array = [NSArray arrayWithObjects:objects count:count];
How dictionary literals work
// when you write this:
dict = #{k1 : o1, k2 : o2, k3 : o3 };
// compiler generates:
id objects[] = { o1, o2, o3 };
id keys[] = { k1, k2, k3 };
NSUInteger count = sizeof(objects) / sizeof(id);
dict = [NSDictionary dictionaryWithObjects:objects
forKeys:keys
count:count];
More on array subscripting
#implementation SongList {
NSMutableArray *_songs;
}
- (Song *)replaceSong:(Song *)newSong atindex:(NSUinteger)idx {
Song *oldSong = [_songs objectAtIndex:idx];
[_songs replaceObjectAtindex:idx withObject:newSong];
return oldSong;
}
#implementation SongList {
NSMutableArray *_songs;
}
- (Song *)replaceSong:(Song *)newSong atindex:(NSUinteger)idx {
Song *oldSong = _songs[idx];
_songs[idx] = newSong;
return oldSong;
}
More on dictionary subscripting
#implementation Database {
NSMutableDictionary *_storage;
}
- (id)replaceObject:(id)newObject forKey:(id <NSCopying>)key {
id oldObject = [_storage objectForKey:key];
[_storage setObject:object forKey:key];
return oldObject;
}
#implementation Database {
NSMutableDictionary *_storage;
}
- (id)replaceObject:(id)newObject forKey:(id <NSCopying>)key {
id oldObject = _storage[key];
_storage[key] = newObject;
return oldObject;
}
[Edit 3]
Mike Ash has a great writeup about these new literals. If you want to know more about this stuff, make sure to check it out.
The Objective-C compiler has hardcoded knowledge of the memory layout of instances of the NSConstantString class, aka the __CFConstantString class. Check out the RewriteObjCStringLiteral function in lib/Rewrite/RewriteModernObjC.cpp in the clang source code. The compiler simply emits data that matches the layout of instances of the NSConstantString class.
There are a couple of possibilities for literal NSArray and NSDictionary instances. They could do something like what they did for literal strings - hardcode the instance layout (for a special subclass) in the compiler and emit data in that layout. Or they could have the compiler emit code that simply creates an instance at runtime.
From “Objective-C Literals”
1) NSNumber, NSDictionary and NSArray literals are available in Xcode 4.4.
2) NSDictionary and NSArray subscripting need "Xcode 4.4 and OS X 10.8 or later SDK" or "Xcode 4.5 and iOS 6 or later SDK"
Looks to me like the subscripting needs runtime support and hence won't work before iOS6.
Apple LLVM Compiler 4.0 added literal support for Objective-C. It starts from at sign #
NSNumber Literals
NSNumber *someBool = [NSNumber numberWithBool:YES];
//BOOL literal
NSNumber *someBool = #YES;
NSNumber *someChar= [NSNumber numberWithChar:'a'];
//character literal
NSNumber *someChar = #'a';
NSNumber *someInt = [NSNumber numberWithInt:1];
NSNumber *someInt = [NSNumber numberWithUnsignedInt:1U];
NSNumber *someInt = [NSNumber numberWithLong:1L];
NSNumber *someInt = [NSNumber numberWithLongLong:1LL];
//integer literal
NSNumber *someInt = #1;
NSNumber *someInt = #1U;
NSNumber *someInt = #1L;
NSNumber *someInt = #1LL;
NSNumber *someFloat = [NSNumber numberWithFloat:3.141592654F];
NSNumber *someFloat = [NSNumber numberWithDouble:3.1415926535];
//float literal
NSNumber *someFloat = #3.141592654F;
NSNumber *someFloat = #3.1415926535;
Collection Literals
NSArray *someArray = [NSArray arrayWithObjects: #"A", #"B", #"C", nil];
//array literal
NSArray *someArray = #[ #"A", #"B", #"C" ];
NSDictionary *someDict = [NSDictionary dictionaryWithObjectsAndKeys:
#"key1", #"value1",
#"key1", #"value2",
nil];
//dictionary literal
NSDictionary *someDict = #{ #"Character" : #"Zelda",
#"key1" : #"value2",
#"key2" : #value2 };
Collection Subscripting
NSString *var1 = [someArray objectAtIndex:0]; // Returns 'A'
NSString *var2 = [someDict objectForKey:#"key1"]; // Returns 'value1'
//Collection Subscripting
//read
NSString *var1 = someArray[0]; // Returns 'A'
NSString *var2 = someDict[#"key1"]; // Returns 'value1'
//write to mutable collection
someArray[0] = #"AA";
someDict[#"key1"] = #"value11";
Boxed Expressions - C-style expression into an Objective-C. Works with numbers, enums, structs
//Syntax #( <expression> )
[NSNumber numberWithInt:(INT_MAX + 1)];
//Boxed Expressions
NSNumber *var = #(INT_MAX + 1);

What are the details of "Objective-C Literals" mentioned in the Xcode 4.4 release notes?

I was going through the release notes for Xcode 4.4 and noticed this:
LLVM 4.0 Compiler
Xcode now includes the Apple LLVM Compiler version 4.0, including the following newObjective-C language features:
[...]
- Objective-C literals: create literals for NSArray, NSDictionary, and NSNumber, just the same as the literals for NSString
I'm intrigued about this feature. It's not entirely clear to me just how literals for NSString work and how one could use them on NSArray, NSDictionary, and NSNumber.
What are the details?
Copied verbatim from http://cocoaheads.tumblr.com/post/17757846453/objective-c-literals-for-nsdictionary-nsarray-and:
Objective-C literals: one can now create literals for NSArray, NSDictionary, and NSNumber (just like one can create literals for NSString)
NSArray Literals
Previously:
array = [NSArray arrayWithObjects:a, b, c, nil];
Now:
array = #[ a, b, c ];
NSDictionary Literals
Previously:
dict = [NSDictionary dictionaryWithObjects:#[o1, o2, o3]
forKeys:#[k1, k2, k3]];
Now:
dict = #{ k1 : o1, k2 : o2, k3 : o3 };
NSNumber Literals
Previously:
NSNumber *number;
number = [NSNumber numberWithChar:'X'];
number = [NSNumber numberWithInt:12345];
number = [NSNumber numberWithUnsignedLong:12345ul];
number = [NSNumber numberWithLongLong:12345ll];
number = [NSNumber numberWithFloat:123.45f];
number = [NSNumber numberWithDouble:123.45];
number = [NSNumber numberWithBool:YES];
Now:
NSNumber *number;
number = #'X';
number = #12345;
number = #12345ul;
number = #12345ll;
number = #123.45f;
number = #123.45;
number = #YES;
[Edit]
zxoq at http://news.ycombinator.com/item?id=3672744 has added more interesting new subscripting. (Added with literals):
arr[1] === [arr objectAtIndex:1]
dict[#"key"] === [dict objectForKey:#"key"]
[Edit 2]
The new ObjC literals were discussed in multiple WWDC 2012 sessions. I intentionally didn't remove the the filenames and the time of each slide so you can find them for yourself if you feel like. They are essentially the same thing as stated in this post, but there are also a few new things that I'll mention above the images.
Please note that images are all big. Simply drag them into another tab to view them in their original size
[NSNumber numberWithint:42]
[NSNumber numberWithDouble:10.8]
[NSNumber numberWithBool:YES]
[NSNumber numberWithint:6 + x * 2012]
#42
#10.8
#YES
#(6 + x * 2012)
[NSArray arrayWithObjects: a, b, c, nil]
[array objectAtIndex:i]
[NSDictionary dictionaryWithObjectsAndKeys: v1, k1, v2, k2, nil];
[dictionary valueForKey:k]
#[a, b, c]
array[i]
#{k1:v1, k2:v2}
dictionary[k]
This part is new. Expression Literals
When you have an expression (M_PI / 16 for example) you should put it inside parenthesis.
This syntax works for numeral expressions, booleans, finding an index in a (C-) string, boolean values, enum constants, and even character strings!
NSNumber *piOverSixteen = [NSNumber numberWithDouble: (M_PI / 16)];
NSNumber *hexDigit = [NSNumber numberWithChar:"0123456789ABCDEF"[i % 16]];
NSNumber *usesScreenFonts = [NSNumber numberWithBool:[NSLayoutManager usesScreenFonts]];
NSNumber *writingDirection = [NSNumber numberWithInt:NSWritingDirectionLeftToRight];
NSNumber *path = [NSString stringWithUTF8String: getenv("PATH")];
NSNumber *piOverSixteen = #( M_PI / 16 );
NSNumber *hexDigit = #( "0123456789ABCDEF"[i % 16] );
NSNumber *usesScreenFonts = #( [NSLayoutManager usesScreenFonts] );
NSNumber *writingDirection = #( NSWritingDirectionLeftToRight );
NSNumber *path = #( getenv("PATH") );
More about character strings and how/when you can use this literal syntax:
NSString *path = [NSString stringWithUTF8String: getenv("PATH")];
for (NSString *dir in [path componentsSeparatedByString: #":"]) {
// search for a file in dir...
}
NSString *path = #( getenv("PATH") );
for (NSString *dir in [path componentsSeparatedByString: #":"]) {
// search for a file in dir...
}
How array literals work
// when you write this:
array = #[a, b, c ];
// compiler generates:
id objects[] = { a, b, c };
NSUInteger count = sizeof(objects) / sizeof(id);
array = [NSArray arrayWithObjects:objects count:count];
How dictionary literals work
// when you write this:
dict = #{k1 : o1, k2 : o2, k3 : o3 };
// compiler generates:
id objects[] = { o1, o2, o3 };
id keys[] = { k1, k2, k3 };
NSUInteger count = sizeof(objects) / sizeof(id);
dict = [NSDictionary dictionaryWithObjects:objects
forKeys:keys
count:count];
More on array subscripting
#implementation SongList {
NSMutableArray *_songs;
}
- (Song *)replaceSong:(Song *)newSong atindex:(NSUinteger)idx {
Song *oldSong = [_songs objectAtIndex:idx];
[_songs replaceObjectAtindex:idx withObject:newSong];
return oldSong;
}
#implementation SongList {
NSMutableArray *_songs;
}
- (Song *)replaceSong:(Song *)newSong atindex:(NSUinteger)idx {
Song *oldSong = _songs[idx];
_songs[idx] = newSong;
return oldSong;
}
More on dictionary subscripting
#implementation Database {
NSMutableDictionary *_storage;
}
- (id)replaceObject:(id)newObject forKey:(id <NSCopying>)key {
id oldObject = [_storage objectForKey:key];
[_storage setObject:object forKey:key];
return oldObject;
}
#implementation Database {
NSMutableDictionary *_storage;
}
- (id)replaceObject:(id)newObject forKey:(id <NSCopying>)key {
id oldObject = _storage[key];
_storage[key] = newObject;
return oldObject;
}
[Edit 3]
Mike Ash has a great writeup about these new literals. If you want to know more about this stuff, make sure to check it out.
The Objective-C compiler has hardcoded knowledge of the memory layout of instances of the NSConstantString class, aka the __CFConstantString class. Check out the RewriteObjCStringLiteral function in lib/Rewrite/RewriteModernObjC.cpp in the clang source code. The compiler simply emits data that matches the layout of instances of the NSConstantString class.
There are a couple of possibilities for literal NSArray and NSDictionary instances. They could do something like what they did for literal strings - hardcode the instance layout (for a special subclass) in the compiler and emit data in that layout. Or they could have the compiler emit code that simply creates an instance at runtime.
From “Objective-C Literals”
1) NSNumber, NSDictionary and NSArray literals are available in Xcode 4.4.
2) NSDictionary and NSArray subscripting need "Xcode 4.4 and OS X 10.8 or later SDK" or "Xcode 4.5 and iOS 6 or later SDK"
Looks to me like the subscripting needs runtime support and hence won't work before iOS6.
Apple LLVM Compiler 4.0 added literal support for Objective-C. It starts from at sign #
NSNumber Literals
NSNumber *someBool = [NSNumber numberWithBool:YES];
//BOOL literal
NSNumber *someBool = #YES;
NSNumber *someChar= [NSNumber numberWithChar:'a'];
//character literal
NSNumber *someChar = #'a';
NSNumber *someInt = [NSNumber numberWithInt:1];
NSNumber *someInt = [NSNumber numberWithUnsignedInt:1U];
NSNumber *someInt = [NSNumber numberWithLong:1L];
NSNumber *someInt = [NSNumber numberWithLongLong:1LL];
//integer literal
NSNumber *someInt = #1;
NSNumber *someInt = #1U;
NSNumber *someInt = #1L;
NSNumber *someInt = #1LL;
NSNumber *someFloat = [NSNumber numberWithFloat:3.141592654F];
NSNumber *someFloat = [NSNumber numberWithDouble:3.1415926535];
//float literal
NSNumber *someFloat = #3.141592654F;
NSNumber *someFloat = #3.1415926535;
Collection Literals
NSArray *someArray = [NSArray arrayWithObjects: #"A", #"B", #"C", nil];
//array literal
NSArray *someArray = #[ #"A", #"B", #"C" ];
NSDictionary *someDict = [NSDictionary dictionaryWithObjectsAndKeys:
#"key1", #"value1",
#"key1", #"value2",
nil];
//dictionary literal
NSDictionary *someDict = #{ #"Character" : #"Zelda",
#"key1" : #"value2",
#"key2" : #value2 };
Collection Subscripting
NSString *var1 = [someArray objectAtIndex:0]; // Returns 'A'
NSString *var2 = [someDict objectForKey:#"key1"]; // Returns 'value1'
//Collection Subscripting
//read
NSString *var1 = someArray[0]; // Returns 'A'
NSString *var2 = someDict[#"key1"]; // Returns 'value1'
//write to mutable collection
someArray[0] = #"AA";
someDict[#"key1"] = #"value11";
Boxed Expressions - C-style expression into an Objective-C. Works with numbers, enums, structs
//Syntax #( <expression> )
[NSNumber numberWithInt:(INT_MAX + 1)];
//Boxed Expressions
NSNumber *var = #(INT_MAX + 1);

How can I create an NSArray with float values

I want to make a float value array. How can I do this? My code is:
NSArray *tmpValue = [[NSArray alloc] init];
total = total + ([[self.closeData objectAtIndex:i]floatValue] - total)* expCarpan;
firstValue = total;
NSArrays only take object types. You can add various non-object types to an NSArray by using the NSNumber wrapper:
NSNumber *floatNumber = [NSNumber numberWithFloat:myFloat];
[myArray addObject:floatNumber]; // Assuming `myArray` is mutable.
And then to retrieve that float from the array:
NSNumber *floatNumber = [myArray objectAtIndex:i];
float myFloat = [floatNumber floatValue];
(As you have done in your code above).
Update:
You can also use the NSValue wrapper in the same way as NSNumber for other non-object types, including CGPoint/Size/Rect/AffineTransform, UIOffset/EdgeInsets and various AV Foundation types. Or you could use it to store pointers or arbitrary bytes of data.
The NSArray class can only contain instances of other Objective-C objects. Fortunately, Apple already has several Objective-C object types for encapsulating C primitive types. For instance, NSNumber can incapsulate many different types of C numbers (integers, floats, etc.). NSValue can incapsulate arbitrary structures, CGPoints, pointers, etc. So, you can use NSNumber and float in conjunction with NSArray as follows:
NSArray * myArray;
NSNumber * myFloatObj = [NSNumber numberWithFloat:3.14];
myArray = [NSArray arrayWithObjects:myFloatObj, nil];
You can then get the original float value from the first NSNumber of the array:
NSNumber * theNumber = [myArray objectAtIndex:0];
float theFloat = [theNumber floatValue];
Alternatively, you can turn this into a one-liner:
float theFloat = [[myArray objectAtIndex:0] floatValue];
Primitive types can't be included in a NSArray, which is only for objects. For numbers, use NSNumber to wrap your floats.
NSNumber *n1 = [NSNumber numberWithFloat:1.2f];
NSNumber *n2 = [NSNumber numberWithFloat:1.4f];
NSArray *array = [NSArray arrayWithObjects:n1, n2, nil];

Expandable Collections in Objective-C?

I was checking out this question which has this code
- (NSArray *) percentagesRGBArray:(float[]) rgbArray
{
NSNumber *red = [NSNumber numberWithFloat:rgbArray[0] / 255];
NSNumber *green = [NSNumber numberWithFloat:rgbArray[1] / 255];
NSNumber *blue = [NSNumber numberWithFloat:rgbArray[2] / 255];
NSNumber *alpha = [NSNumber numberWithFloat:rgbArray[3]];
return [NSArray arrayWithObjects:red, green, blue, alpha, nil];
}
and I thought, "that's terrible, what if you have more than three colors?" I know, you don't, but what if you did have count-1 colors and an alpha? Let's say you had [rgbArray count] (does count even work for a real array?) Using only objective-C, what the normal way that you would return an NSArray of n objects?
I just tried to work it out but I still don't have the chops to do this in objective-C. Here's my failed attempt:
- (NSArray *) what:(float[]) rgbArray
{
int len = sizeof(rgbArray)/sizeof(float); // made up syntax
NSLog(#"length is wrong dummy %d", len);
NSNumber *retVal[len];
for (int i=0;i<(len-1);i++) {
NSNumber *red = [NSNumber numberWithFloat:rgbArray[0] / 255];
retVal[i] = red;
[red release];
}
retVal[len-1] = [NSNumber numberWithFloat:rgbArray[len-1]];
return [NSArray arrayWithObjects:retVal count:len];
}
You can use an NSMutableArray.
You can add & remove items from it and it is a subclass of NSArray so it can be passed to any method expecting an NSArray.
Well, just as arrayWithObjects:count: has count: part, you can do
- (NSArray *) what:(float[]) rgbArray count:(int)len
{
NSMutableArray*result=[NSMutableArray array];
for (int i=0;i<len;i++) {
NSNumber *red = [NSNumber numberWithFloat:rgbArray[0] / 255];
[result addObject:red];
}
return result;
}
If you want, I can be as close as what you wrote, which would be
- (NSArray *) what:(float[]) rgbArray count:(int)len
{
NSNumber**retVal=malloc(len*sizeof(NSNumber*));
for (int i=0;i<len;i++) {
NSNumber *red = [NSNumber numberWithFloat:rgbArray[0] / 255];
retVal[i]=red;
}
NSArray*result=[NSArray arrayWithObjects:retVal count:len];
free(retVal);
return result;
}
At this stage, it's not really a question of Objective-C, but is a question of just plain C, right? Your questions are
how to dynamically allocate an array in C and
how to get the size of an array from a function in C.
The answers are
You use malloc.
You can't do that, so you need to pass that to the function.
That's it.
So, if you have a question about how to deal with C arrays, you should ask C experts... there's nothing special about Objective-C, except the method declaration syntax.