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

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);

Related

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);

NSDictionary With Integer Values

I'm working on a game with monsters. Each one has a list of stats that are all going to be ints. I can set up each stat as it's own variable but I'd prefer to keep them in an NSDictionary since they are all related. I'm running into a problem when I'm trying to change the value's of each stat.
What I Have:
-(id) init {
self = [super init];
if(self) {
stats = [NSDictionary dictionaryWithObjectsAndKeys:
#"Attack", 0,
#"Defense", 0,
#"Special Attack", 0,
#"Special Defense", 0,
#"HP", 0, nil];
}
return self;
}
What I want to do
-(void) levelUp {
self.level++;
[self.stats objectForKey:#"Attack"] += (level * 5);
[self.stats objectForKey:#"Defense"] += (level * 5);
[self.stats objectForKey:#"Special Attack"] += (level * 5);
[self.stats objectForKey:#"Special Defense"] += (level * 5);
[self.stats objectForKey:#"HP"] += (level * 5);
}
Error I'm Getting
Arithmetic on pointer to interface 'id', which is not a constant size in non-fragile ABI
So it seems obvious to me that the reason I'm getting the problem is that I'm getting an object returned from objectForKey instead of an integer. So I tried to do the intValue method on the object I'm getting but that gave me another error, specifically:
Assigning to 'readonly' return result of an objective-c message not allowed
I'm out of ideas for how to fix this. Any help? Would it be better to just give up the idea to store them all together and just use an int property for each stat?
You can only store objects, not primitives, within Cocoa collection classes, so to store numbers you need to use NSNumber objects.
You need to use an NSMutableDictionary if you wish to change the contents later.
Your call to dictionaryWithObjectsAndKeys has the keys and values reversed.
Your stats object is not being retained, so it will be released next time round the run loop (if you're using manual reference counting, that is).
You want:
stats = [[NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:0], #"Attack",
[NSNumber numberWithInt:0], #"Defense",
[NSNumber numberWithInt:0], #"Special Attack",
[NSNumber numberWithInt:0], #"Special Defense",
[NSNumber numberWithInt:0], #"HP",
nil] retain];
In order to change the values you need to create a new NSNumber object as they are immutable, so something like:
NSNumber *num = [stats objectForKey:#"Attack"];
NSNumber *newNum = [NSNumber numberWithInt:[num intValue] + (level * 5)];
[stats setObject:newNum forKey:#"Attack"];
All pretty tedious if you ask me; there must be an easier way, for example how about creating an Objective-C class to store and manipulate this stuff?
NSDictionarys store NSObject*s. In order to use them with integer values, you unfortunately need to use something like NSNumber. So your initialization would look like:
-(id) init {
self = [super init];
if(self) {
stats = [NSDictionary dictionaryWithObjectsAndKeys:
#"Attack", [NSNumber numberWithInt:0],
#"Defense", [NSNumber numberWithInt:0],
#"Special Attack", [NSNumber numberWithInt:0],
#"Special Defense", [NSNumber numberWithInt:0],
#"HP", [NSNumber numberWithInt:0], nil];
}
return self;
}
Then you would have to retrieve them as numbers:
NSNumber *atk = [self.stats objectForKey:#"Attack"];
int iAtk = [atk intValue];
[self.stats setObject:[NSNumber numberWithInt:iAtk] forKey:#"Attack"];
EDIT
Of course, in order to do this, self.stats needs to be an NSMutableDictionary
Adapting #trojanfoe's answer for modern Objective-C with nice syntax sugar:
stats = [#{#"Attack" : #0,
#"Defense" : #0,
#"Special Attack" : #0,
#"Special Defense" : #0,
#"HP" : #0} mutableCopy];
And to update a value:
stats[#"Attack"] = #([stats[#"Attack"] intValue] + (level * 5));

Whats the best way to convert an NSString to an NSInteger based on an array of values?

I want to convert characters into integers based on predetermined values, for example:
a = 0
b = 1
c = 2
d = 3
etc...
Right now I'm doing it with an If/Else If, I just want to know if there is a faster/better way I should be doing it because the list of conversions may get quite long.
Here's what I'm using now:
-(NSInteger)ConvertToInt:(NSString *)thestring {
NSInteger theint;
if([thestring isEqualToString:#"a"] == YES){
theint = 0;
} else if ([thestring isEqualToString:#"b"] == YES){
theint = 1;
} //etc...
return theint;
}
This works fine, but as I said, if it makes more sense can I create an array with all the key/values then just run through that to return the integers?
Please provide examples as I'm a beginner with Objective C/iOS. I come from Web languages.
Thanks!
EDIT: Thanks for the help everyone. I used taskinoors answer but I replaced the NSDictionary which was giving error messages with this:
NSDictionary *dict;
dict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:0], #"a",
[NSNumber numberWithInt:1], #"b",
[NSNumber numberWithInt:2], #"c", nil];
unichar ch = [thestring characterAtIndex:0];
theint = ch - 'a';
Note that, 'a' with a single quote is character a, not string "a".
If the values are not regular like your example then you can store all predefined values into a dictionary. For example:
"a" = 5;
"b" = 1;
"c" = 102;
NSArray *values = [NSArray arrayWithObjects:[NSNumber numberWithInt:5],
[NSNumber numberWithInt:1], [NSNumber numberWithInt:102], nil];
NSArray *keys = [NSArray arrayWithObjects:#"a", #"b", #"c", nil];
NSDictionary *dic = [NSDictionary dictionaryWithObjects:values forKeys:keys];
theint = [[dic valueForKey:thestring] intValue];
If you wanted to keep some flexibility in what strings map to what integers, and your integers run from 0 to n-1 where you have n unique items in the array, you could do something like this:
-(NSInteger)ConvertToInt:(NSString *)thestring {
NSArray *arr = [NSArray arrayWithObjects:#"a", #"b", #"c", #"d", nil];
NSInteger theint = [arr indexOfObject:thestring];
return theint;
}
Now this will build the array each time, which would be very inefficient, the optimal way would be to build the array once in your class, and then just use a reference to that array with the indexOfObject method call.

can't get value from NSDictionary which expected to have NSNumber as output

I have created a NSDictionary like following :
NSArray * alphabets = [NSArray arrayWithObjects:#"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",nil];
alphaToNum = [NSMutableDictionary dictionary];
numToAlpha = [NSMutableDictionary dictionary];
for(NSString* character in alphabets)
{
[alphaToNum setObject:[NSNumber numberWithInteger:index] forKey:character];
[numToAlpha setObject:character forKey:[NSNumber numberWithInteger:index]];
index++;
}
now I want to access to "numToAlpha" like following :
NSInteger code1;
NSNumber * nn = [numToAlpha objectForKey:code1];
and I'll get error whereas in manual for objectforkey it clearly said (id)objectforkey(id) which means anything!
NSInteger is not an object. id refers to any object type. You need to use [NSNumber numberWithInteger:code1] as you are already doing in your code sample.

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.