how can I do this? Basically I want to store RGB color values that can be retrieved in response to a color name. My C++ code uses boost unordered_map to do this:
("SlateBlue1", Color(0.5137f, 0.4353f,1.0f))
("tan3", Color(0.8039f, 0.5216f, 0.2471f))
("grey32", Color(0.3216f, 0.3216f, 0.3216f))
Color is a class that stores the 3 values.
Trying to do this in Objective-C is tying me up in knots and weird errors! Most of the dictionary examples I've found are simply matching 2 strings. Of course I can just use the C++ code in a .mm file, but if anyone has any ideas how to achieve this the Obj-C way, I'd be pleased to learn, thanks.
It's exactly the same in Cocoa - use a NSDictionary instead of the unordered_map, NSString instead of const char* for the key and UIColor instead of Color for the object and you're done.
E.g., [NSDictionary dictionaryWithObject: [UIColor redColor] forKey: #"Red"]] to create a single-entry map. Adjust for multiple colors and you're all set. Use NSColor if you're not on iOS.
You might be missing the key point that a dictionary is an (almost) untyped collection, so it can store a heterogenous set of object types using a heterogenous set of key types.
If you're color object extends NSObject, you should be able to store those colors as the values in your NSDictionary.
NSDictionary *colors = [[NSDictionary alloc] initWithObjectsAndKeys:Color1, #"SlateBlue1", Color2, #"tan3", Color3, #"grey32", nil ];
That should work and then you'd use
Color *mycolor = [colors objectForKey:#"SlateBlue1"];
And then access your colors from your object.
Also, not sure of the purpose of your color object but you could use NSColor for Cocoa or UIColor for Cocoa-touch to store these as well.
(I haven't tested this code, just wrote from memory)
If you want to use a UIColor object or similar, the other answers cover it. If you really want to store three floats, you have a couple of options. You can store an NSArray of three NSNumbers for each triple of floats:
NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:
[NSArray arrayWithObjects:[NSNumber numberWithFloat:.5], [NSNumber numberWithFloat:.7], [NSNumber numberWithFloat:.2], nil], #"bleem",
... // more array/string pairs
nil];
Or you can use an NSData for each triple of floats:
NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:
[NSData dataWithBytes:&(float[]){ .5, .7, .2} length:3*sizeof(float)], #"bleem",
... // more data/string pairs
nil];
Related
I am very new to objective-C and came across the NSDictionary method allKeysForObject:. Seems very useful. However, I have a NSDictionary which has several NSArrays (all of length 2) and which are keyed by NSStrings. Basically, the keys are items and the arrays define their two properties. If I wanted to pull all the item names that have a certain property, could this be done with something like allKeysForObject, or should I just loop over the dictionary and grow a mutable array (seems inefficient).
I'd include a code snippet, but I feel like this question is conceptual enough that code wouldn't really clarify anything. Oh, what the hell. Here's some simplified code:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObjects:[NSNumber numberWithInt:1],[NSNumber numberWithInt:2],nil],#"Car",[NSArray arrayWithObjects:[NSNumber numberWithInt:2],[NSNumber numberWithInt:3],nil],#"Boat",nil];
NSLog(#"%#",[dict allKeysForObject:???]); // this is the line I am not at all sure about.
EDIT: Thank you for the responses so far. I was not clear about my question, though. I am looking for a way to do something more general. I don't want to retrieve all keys for a particular object, say [1,2], but I want to look in the dictionary for all arrays including the NSNumber 1 and return those keys. So if I added #"Plane",[NSArray arrayWithObjects:[NSNumber numberWithInt:1],[NSNumber numberWithInt:3],nil], I'd like to somehow query for the NSNumber 1 and get #"Car" and #"Plane". I am getting the sense that this is not what this method was designed to do.
You are looking for -keysOfEntriesPassingTest:...
NSArray * selectedKeys = [dict keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop)
{
return [obj containsObject:[NSNumber numberWithInt:2]];
}];
In your example, if you call
[dict allKeysForObject: [NSArray arrayWithObjects:
[NSNumber numberWithInt:2],
[NSNumber numberWithInt:3],
nil]]]
you should get an array containing just #"Boat"
In Objective-C, how to do something like is
int array[] = {1, 2, 3, 4};
in pure C?
I need to fill NSArray with NSStrings with the smallest overhead (code and/or runtime) as possible.
It's not possible to create an array like you're doing at compile time. That's because it's not a "compile time constant." Instead, you can do something like:
static NSArray *tArray = nil;
-(void)viewDidLoad {
[super viewDidLoad];
tArray = [NSArray arrayWithObjects:#"A", #"B", #"C", nil];
}
If it's truly important that you have this precompiled, then I guess you could create a test project, create the array (or whatever object) you need, fill it, then serialize it using NSKeyedArchiver (which will save it to a file), and then include that file in your app. You will then need to use NSKeyedUnarchiver to unarchive the object for use. I'm not sure what the performance difference is between these two approaches. One advantage to this method is that you don't have a big block of code if you need to initialize an array that includes a lot of objects.
use this
NSArray *array = [NSArray arrayWithObjects:str1,str2, nil];
As far as i understand you need a one-dimentional array
You can use class methods of NSArray.. For instance
NSString *yourString;
NSArray *yourArray = [[NSArray alloc] initWithObjects:yourString, nil];
If you need more, please give some more detail about your issue
Simple as that: NSArray<NSString*> *stringsArray = #[#"Str1", #"Str2", #"Str3", ...]; Modern ObjectiveC allows generics and literal arrays.
If you want shorter code, then NSArray *stringsArray = #[#"Str1", #"Str2", #"Str3", ...];, as the generics are optional and help only when accessing the array elements, thus you can later in the code cast back to the templatized array.
Why does the following result in a BAD_ACCESS error?
NSDictionary *header=[[NSDictionary alloc]initWithObjectsAndKeys:#"fred",#"title",1,#"count", nil];
Can you have different types of objects as values in NSDictionary, including another NSDictionary?
You can put any type of object into an NSDictionary. So while #"fred" is OK, 1 is not, as an integer is not an object. If you want to put a number in a dictionary, wrap it in an NSNumber:
NSDictionary *header = { #"title": #"fred", #"count": #1 };
Not the way you have it. The number 1 is a primitive and the NSArray object can hold only objects. Create a NSNumber for the "1" and then it will store it.
An NSDictionary can only contain Objective-C objects in it (such as NSString and NSArray), it cannot contain primitive types like int, float, or char*. Given those constraints, heterogeneous dictionaries are perfectly legal.
If you want to include a number such as 1 as a key or value, you should wrap it with an NSNumber:
NSDictionary *header=[[NSDictionary alloc] initWithObjectsAndKeys:
#"fred", #"title",
[NSNumber numberWithInt:1], #"count",
nil];
The only requirement is that is be an object. It's up to you to handle the objects properly in your code, but presumably, you can keep track of their types based on the keys.
1 is not an object. If you want t o put a number into a dictionary you may want to convert it to an NSNumber.
Does iOS support something like
s = { x:3,y:5 , o:{x:0,y:1}}
like in Javascript?
Or what is the best way to use something like this in iOS?
A literal translation would be :
NSDictionary *s = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:3], #"x",
[NSNumber numberWithInt:5], #"y",
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:0], #"x",
[NSNumber numberWithInt:1], #"y",
nil ], #"o",
nil ];
But literal translations, even in programming languages, are not best. It all depends on the context and what you need to accomplish. There's probably less code required depending on what you need.
EDIT: There's now a new literal syntax allowing to shrink this code further:
NSDictionary *s = #{ #"x": #3
, #"y": #5
, #"o": #{ #"x": #0, #"y": #1}
};
This syntax implicitely creates the NSDictionary & NSNumber objects.
No, there is no shortcut syntax for dicts in Objective-C. You have to do it manually.
It depends exactly what type of object you mean. There really isn't a generic answer here.
If you're referring to an NSDictionary for example, you could use
+ (id)dictionaryWithObjects:(NSArray *)objects forKeys:(NSArray *)keys
or any of the variants documented on the same page.
You could write a setter or helper method that could take a string in the above format, syntax check it, parse it, and use the string fields to create or modify an NSDictionary for you automatically from a one line call.
But it's not a built function of Obj C or the NSFoundation frameworks. Some JSON Category additions might do something like this though.
What you can do is create a JSON string and then use a JSON framework to generate the corresponding NSArray/NSDictionary structure. This would approach what you are trying to do, but not quite there... Then you can describe your object structure with something like this:
{"x": 3, "y" : 5, "o" : {"x": 0, "y" : 1}}
Main limitation is that you won't have numeric types out of the box, but you can use NSNumber, NSScanner and so on to get them.
No, it does not support. But i am sorry, im not fammiliar with JS.
To creat a obj in iOS you do the following:
ObjName *objVar;
then you set its properties:
#property (nonatomic, strong) ObjName *objVar;
then you syntesize it in the .m
#syntesize objVar;
and the you alloc it and init it in the desired method.
i have an enumeration say gender, now i want to associate it to string values to use in the view inside a picker view. It's cocoa-touch framework and objective-c as language.
So i don't know of a way to set the data source of the picker view as the enumeration, as could have been done in other frameworks. So i've been told i have to make array of enum values. and then i tried to add thos into an NSMutableDictionary with their respective string values.
So i ended up with
NSArray* genderKeys = [NSArray arrayWithObjects:#"Male",#"Female",nil] ;
NSArray* genderValues = [NSArray arrayWithObjects:[NSNumber numberWithInt:male],[NSNumber numberWithInt:female],nil];
for(int i =0;i<[genderKeys count];i++)
[_genderDictionary setValue:[genderValues objectAtIndex:i] forKey:[genderKeys objectAtIndex:i]];
and it's not working saying it's not a valid key, and i've read the key-coding article and i know now what's key and whats keypath, but still how can i solve that. It's ruining my life, Please help.
Sorry guys, i was using NSDictionary for _genderDictionary.But i had in my mind that it was nsmutable. Thank you all.
Be careful using UI text as keys into your database. What amount when you need to localise your application to french, chinese, arabic etc?
That works for me. Running this (your code, with the first line added so it would compile) seems to work fine.
NSMutableDictionary *_genderDictionary = [NSMutableDictionary dictionary];
NSArray* genderKeys = [NSArray arrayWithObjects:#"Male",#"Female",nil] ;
NSArray* genderValues = [NSArray arrayWithObjects:[NSNumber numberWithInt:1],[NSNumber numberWithInt:2],nil];
for(int i =0;i<[genderKeys count];i++)
[_genderDictionary setValue:[genderValues objectAtIndex:i] forKey:[genderKeys objectAtIndex:i]];
NSLog()-ing _genderDictionary outputs this
{
Female = 2;
Male = 1;
}
edit: re-reading your question, makes me think what you are looking for is the delegate methods of UIPickerView... implementing –pickerView:titleForRow:forComponent: is where you set the text that appears in the picker. If you have an NSArray of genders, you would do something like return [_genderArray objectAtIndex:row]; That way you don't need to fuss around with a dictionary and keys.
edit 2: a picker's datasource can't be an NSArray or NSDictionary directly. It has to be an object that implements UIPickerView's datasource/delegate protocol (which I suppose you could do with a subclass of NSArray, but that'd be cah-ray-zay!).
If I understand you correctly, you try to create a pre-populated dictionary.
You could use [NSDictionary dictionaryWithObjectsAndKeys:] for that.
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithUnsignedInt:0], #"Male",
[NSNumberWithUnsignedInt:1], #"Female", nil]