Objective-C identifier from NSString - objective-c

I want to pass an NSString to a method and have that particular NSString name a new NSSMutableArray. Confusing? Programmatically looks like this:
+ (void)newMutableArrayWithName:(NSString*)theArrayName
{
NSLog(#"Creating an array that is named: %#",theArrayName);
NSMutableArray* theArrayName = [[NSMutableArray alloc] init];
}
Unfortunately, "theArrayName" is not affiliated with the argument passed to the method. Is there any way this is achievable?

The name of a variable is used by the compiler, and is set at compile-time, not at run time.
If you need to be able to associate a label with an array, I suggest that you use an NSDictionary to do something like this
NSString *theArrayName = #"My Cool Array";
NSMutableArray *theArray = [NSMutableArray array];
NSDictionary *theDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
theArray, theArrayName, nil];
You could have multiple "named" arrays in the dictionary, if you wanted, and could access them by the names that you gave them
[theDictionary objectForKey:#"My Cool Array"];

Look into key-value coding for setting the values of existing properties by the property's name, but it appears it can't create a new property. For that, you should just use a dictionary.

Related

Array from different classes

i have a class Devices and several subclasses like mobiles, watches etc.
I just wondering is it possible to create an array from all of these subclasses? I have to create objects from class1 class2 etc and put them to an array. This array must contain objects from different classes. The array must have 200 elements. And can you please give an example.
Thanks in advance
Yup, it's perfectly possible:
NSArray *array = #[
#"a string",
#1337, // a NSNumber
[UIImage imageNamed:#"anImage"],
//... and so on
]
So i think i didn't post the question proper. I have to create objects from class1 class2 etc and put them to an array. This array must contain objects from different classes
I guess you are looking for something like this:
NSMutableArray *yourArray = [[NSMutableArray alloc] init];
ObjectType1 *object1 = [[ObjectType1 alloc] init];
[yourArray addObject: object1];
ObjectType2 *object2 = [[ObjectType2 alloc] init];
[yourArray addObject: object2];
ObjectType3 *object3 = [[ObjectType3 alloc] init];
[yourArray addObject: object3];
This way you'll have an array with 3 items. This are 3 objects each with a different object type. Note that you have a good administration for the reading of the objects.
The following is wrong, because you are reading the first object which is of type ObjectType1, and you are assigning it to ObjectType2.
ObjectType2 *readingObject = [yourArray objectAtIndex:1]; // WRONG!

Create an NSMutableArray that contains several NSMutableDictionary objects

I've looked around and seen several postings concerning sorting NSMutableArray's that contain NSDictionaries, but haven't been able to find some concrete examples of how to actually make an NSMutableArray composed of NSDictionaries.
I am using NSUserDefaults to keep track of a user's preferences for several different items. The NSMutableArray will be used to keep track of the total items, and the NSDictionaries are for the individual preferences concerning each item.
I've written these methods to keep track of items in my preferences class, but I'm not too sure how to initialize the NMutableArray to contain NSDictionaries.
-(NSMutableArray *)deviceListArray
{
return [[NSUserDefaults standardUserDefaults] mutableArrayValueForKey:#"device_list_array"];
}
-(void) setDeviceListArray:(NSMutableArray *)deviceListArray
{
[[NSUserDefaults standardUserDefaults] setObject:deviceListArray forKey:#"device_list_array"];
}
If anyone could point me in the right direction, I would really appreciate it. Thank you very much! Or if someone has a better strategy for keeping track of items, each with different preferences, then that would be awesome too!
Thanks!!
Once you hand an object of to userDefaults, it owns that object - so you cannot go changing properties of dictionaries inside it.
What you can do is a two pass copy, where you have a local mutable array with mutable dictionaries in it. You would create a new mutable array of the same size, then for each mutable dictionary, call [NSDictionary dictionaryWithDictionary:], adding the new non-mutable dictionary to the new array.
If you have mutable objects buried in the dictionaries, well, you need to do the same for that.
All that said, if you have such a huge amount of stuff I suspect you have no properly thought of how to use the defaults system. I almost always just save strings, numbers, colors etc.
EDIT: code
NSMutableArray *array = [NSMutableArray arrayWithCapacity:10];
for(int i=0; i<10; ++i) {
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:10];
// add stuff to the dictionary
[array addObject:dict];
}
// later on want to change second dictionary:
NSMutableDictionary *dict = [array objectAtIndex:1];
// fool around with dict
// no need to re-save it in array, since its mutable
Not sure if this is what you were looking for:
#define kDeviceKey1 #"DeviceKey1"
#define kDeviceKey2 #"DeviceKey2"
#define kDeviceKey3 #"DeviceKey3"
#define kDeviceKey4 #"DeviceKey4"
#define kDeviceID #"DeviceID"
NSMutableArray *devices = [[NSMutableArray alloc]init];
NSMutableDictionary *deviceInfo = [[NSMutableDictionary alloc]init];
// create a dictionary record for earch device which contains thing...
// probably employ some kind of loop
deviceInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:1], kDeviceID,
// #"DeviceName1", kDeviceID, // or this
#"whateverthing1forDevice1", kDeviceKey1,
#"whateverthing2forDevice1", kDeviceKey2,
#"whateverthing3forDevice1", kDeviceKey3,
#"whateverthing4forDevice1", kDeviceKey4,
nil];
[devices addObject:deviceInfo];
// this is just an example, you would have some kind of loop to replace "whateverthing1forDevice1" with actual data
deviceInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:2], kDeviceID,
// #"DeviceName2", kDeviceID, // or this
#"whateverthing1forDevice2", kDeviceKey1,
#"whateverthing2forDevice2", kDeviceKey2,
#"whateverthing3forDevice2", kDeviceKey3,
#"whateverthing4forDevice2", kDeviceKey4,
nil];
[devices addObject:deviceInfo];
NSLog(#"devices: %#", devices);

How to copy NSArray to another NSArray?

I have many different NSArrays, and according to the users choice I want one of them to be copied to a new NSArray. How do I copy one NSArray to another?
There can be several ways for this-
array1 = [array2 copy];
Use initWithArray method.
You can also use initWithArray:copyItems: method. (This if for NSMutableArray)
you can use the
NSArray *_newArray = [NSArray arrayWithArray:_oldArray];
or if you prefer better, you can use:
NSArray *_newArray = [[NSArray alloc] initWithArray:_oldArray];
(in that case the object of the first array won't be copied, that get only a retain front he second NSArray, you can remove the object from any array it won't affect the other array, but if you change any object in any NSArray it will be changed in the other one as well because there is both of the old and the new array is working with the same instance of the objects.)
if your plan is to make another instance of the old objects in the new array:
NSArray *_newArray = [[NSArray alloc] initWithArray:_oldArray copyItems:true];
if you are using the ARC, you won't need to do anything else, if you are not, in the case of both -initWithArray: or -initWithArray:copyItems: you should use the [_newArray release]; to release the array after you don't want to use anymore.
As well as
NSArray *newArray = [oldArray copy];
if you need to add/remove from the new array, the simplest way to make a mutable copy is:
NSMutableArray *editableArray = [oldArray mutableCopy];
The above functions both make shallow copies, for deep copy it's as #holex and #rishi mentioned
NSArray *newArray = [[NSArray alloc] initWithArray:oldArray copyItems:true];
NSMutableArray *editableArray = [[NSMutableArray alloc] initWithArray:oldArray copyItems:true];

objective-c how to create an enumeration array with its string values as keys?

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]

Test NSmutable array from plist before saving

I'm trying to made a cocoa app that read-write to a .plist file.
I can retrieve informations from the .plist, write into, but when a key (only with strings) is empty, the app don't write to the plist.
here a sample:
-
(IBAction)saveBoot:(id)sender {
NSString *errorDesc;
NSString *bootPath = #"/myplist.plist";
NSMutableDictionary *plistBootDict =
[NSMutableDictionary dictionaryWithObjects:
[NSMutableArray arrayWithObjects:
Rescan,
RescanPrompt,
GUI,
InstantMenu,
DefaultPartition,
EHCIacquire,
nil]
forKeys:[NSMutableArray arrayWithObjects:
#"Rescan",
#"Rescan Prompt",
#"GUI",
#"Instant Menu",
#"Default Partition",
#"EHCIacquire",
nil]];
NSData *plistBootData = [NSPropertyListSerialization
dataFromPropertyList:plistBootDict
format:NSPropertyListXMLFormat_v1_0
errorDescription:&errorDesc];
if (bootPath) {
[plistBootData writeToFile:bootPath atomically:NO];
}
else {
NSLog(errorDesc);
[errorDesc release];
}
}
#end
I think i need a loop to check if each key is empty or not (and remove it if empty),
but i've tried different (objectEnumerator, objectForKey:..etc) method whitout success.
If someone can help a beginner like me,
thanks in advance.
Ronan.
The problem is probably that because nil is the terminator for variable argument lists, so if, say, RescanPrompt is nil, the object array will only contain up until that part (so you can't "remove if empty" since it won't exist in the dictionary in the first place). You should probably construct your dictionary piece by piece; something like:
NSMutableDictionary *plistBootDict = [NSMutableDictionary dictionary];
if (Rescan)
[plistBootDisc setObject:Rescan forKey:#"Rescan"];
if (GUI)
[plistBootDisc setObject:GUI forKey:#"GUI"];
// etc
(Also, there's no reason to be using NSMutableArray or NSMutableDictionary if you're never going to be mutating them later.)