How to create a 2D NSArray or NSMutableArray in objective C? - objective-c

I want to ask about the objective C question. I want to create a 2D NSArray or NSMutableArray in objective C. What should I do? The object stored in the array is NSString *. Thank you very mcuh.

This is certainly possible, but i think it's worthy to note that NSArrays can only hold objects, not primitive types.
The way to get around this is to use the primitive wrapper type NSNumber.
NSMutableArray *outer = [[NSMutableArray alloc] init];
NSMutableArray *inner = [[NSMutableArray alloc] init];
[inner addObject:[NSNumber numberWithInt:someInt]];
[outer addObject:inner];
[inner release];
//do something with outer here...
//clean up
[outer release];

Try NSMutableDictionary with NSNumbers as keys and arrays as objects. One dimension will be the keys, the other one will be the objects.
To create the specific "2D array"
NSMutableDictionary *twoDArray = [NSMutableDictionary dictionary];
for (int i = 0; i < 10; i++){
[twoDArray setObject:arrayOfStrings forKey:[NSNumber numberWithInt:i]];
}
To pull the data
NSString *string = [[twoDArray objectForKey:[NSNumber numberWithInt:3]] objectAtIndex:5];
//will pull string from row 3 column 5 -> as an example

Edited to make my answer more applicable to the question. Initially I didn't notice that you were looking for a 2D array. If you know how many by how many you need up front you can interleave the data and have a stride. I know that there are probably other (more objective standard) ways of having arrays inside of an array but to me that gets confusing. An array inside of an array is not a 2 dimensional array. It's just a second dimension in ONE of the objects. You'd have to add an array to each object, and that's not what I think of as a 2 dimensional array. Right or wrong I usually do things in a way that makes sense to me.
So lets say you need a 6x6 array:
int arrayStride=6;
int arrayDepth=6;
NSMutableArray *newArray = [[NSMutableArray alloc] initWithCapacity:arrayStride*arrayDepth];
I prefer to initialize the array by filling it up with objects;
for(int i=0; i<arrayStride*arrayDepth; i++) [newArray addObject #"whatever"];
Then after that you can access objects by firstDim + secondDim*6
int firstDim = 4;
int secondDim = 2;
NSString *nextString = [newArray objectAtIndex:firstDim+secondDim*6];

Related

Create Instance variables at runtime

I want to create instance variables dynamically at runtime, and I want to add these variables to a category. The number of the instance variables may change based on the configuration/properties file which I am using for defining them.
Any ideas??
Use Associative References - this is tricky, but that is the mechanism invented specifically for your use case.
Here is an example from the link above: first, you define a reference and add it to your object using objc_setAssociatedObject; then you can retrieve the value back by calling objc_getAssociatedObject.
static char overviewKey;
NSArray *array = [[NSArray alloc] initWithObjects:# "One", #"Two", #"Three", nil];
NSString *overview = [[NSString alloc] initWithFormat:#"%#", #"First three numbers"];
objc_setAssociatedObject (
array,
&overviewKey,
overview,
OBJC_ASSOCIATION_RETAIN
);
[overview release];
NSString *associatedObject = (NSString *) objc_getAssociatedObject (array, &overviewKey);
NSLog(#"associatedObject: %#", associatedObject);
objc_setAssociatedObject (
array,
&overviewKey,
nil,
OBJC_ASSOCIATION_ASSIGN
);
[array release];
I'd be inclined to just use a NSMutableDictionary (see NSMutableDictionary Class Reference). Thus, you would have an ivar:
NSMutableDictionary *dictionary;
You'd then initialize it:
dictionary = [NSMutableDictionary dictionary];
You can then save values to it dynamically in code, e.g.:
dictionary[#"name"] = #"Rob";
dictionary[#"age"] = #29;
// etc.
Or, if you are reading from a file and don't know what the names of the keys are going to be, you can do this programmatically, e.g.:
NSString *key = ... // your app will read the name of the field from the text file
id value = ... // your app will read the value of the field from the text file
dictionary[key] = value; // this saves that value for that key in the dictionary
And if you're using an older version of Xcode (before 4.5), the syntax is:
[dictionary setObject:value forKey:key];
Depends on exactly what you want to do, the question is vague but if you want to have several objects or several integers or so on, arrays are the way to go. Say you have a plist with a list of 100 numbers. You can do something sort of like this:
NSArray * array = [NSArray arrayWithContentsOfFile:filePath];
// filePath is the path to the plist file with all of the numbers stored in it as an array
That will give you an array of NSNumbers, you can then turn that into an array of just ints if you want like this;
int intArray [[array count]];
for (int i = 0; i < [array count]; i++) {
intArray[i] = [((NSNumber *)[array objectAtIndex:i]) intValue];
}
Whenever you want to get an integer from a certain position, lets say you want to look at the 5th integer, you would do this:
int myNewInt = intArray[4];
// intArray[0] is the first position so [4] would be the fifth
Just look into using a plist for pulling data, it will them be really easy to create arrays of custom objects or variables in your code by parsing the plist.

Load an element value of an array to another array Xcode Objective-C

Here I am getting the cityName1 with the city names like Piscataway, Iselin, Broklyn etc fetched from the tgpList1 array and I need to put the values into an array called item5.
There are 133 records fetched by the above iteration. The following code stores only the last record's cityName1 and not the entire list of city names though inside the loop.
I tried many ways but I am missing something.
tgpList1 is an array.
tgpDAO is an NSObject with two objects NSString *airportCode and NSString *cityName
NSArray *item5 = [[NSArray alloc]init];
for (int currentIndex=0; currentIndex<[tgpList1 count]; currentIndex++)
{
tgpDAO *tgpTable = (tgpDAO *)[self.tgpList1 objectAtIndex:currentIndex];
NSLog(#"The array values are %#",tgpList1);
NSString *cityName1 = tgpTable.cityName;
item5 =[NSArray arrayWithObjects:cityName1, nil];
}
Use mutable array.
{
NSMutableArray *item5 = [[NSMutableArray alloc]initWithArray:nil];
for (int currentIndex=0; currentIndex<[tgpList1 count]; currentIndex++) {
tgpDAO *tgpTable = (tgpDAO *)[self.tgpList1 objectAtIndex:currentIndex];
NSLog(#"The array values are %#",tgpList1);
NSString *cityName1 = tgpTable.cityName;
[item5 addObject:cityName1];
}
}
Instead of
item5 =[NSArray arrayWithObjects:cityName1, nil];
use
[item5 addObject:cityName1];
There are more ways of achieving that. However, this is the one that is designed for that purpose and the most "readable" from my pont of view.
If you need to clear the contents of item5 before then call
[item5 removeAllObjects];
right before the for loop.
What you were doing: arrayWithObjects allways creates a new array that ist made of the objects that are passed to it as aguments. If you do not use ARC, then you would create some serious memory leak with your code because arrayWithObjects creates and retains an object on every loop and on the next loop all references to the array object, that was just created, are lost without being released. If you do ARC then you do not have to worry about in this case.
NSMutableArray *myCities = [NSMutableArray arrayWithCapacity:2]; // will grow if needed.
for( some loop conditions )
{
NSString* someCity = getCity();
[myCities addObject:someCity];
}
NSLog(#"number of cities in array: %#",[myCities count]);

How does one populate an NSMutable array of NSMutableSets?

I am using this code in a loop to populate an NSMutable Array of NSMutableSets (of NSString objects). The index of the NSSet is based on the length of the word.
// if set of this length not initialized yet, initialize set.
wordIndex = [NSString stringWithFormat:#"%d", currentWordLength];
if ([myWordArray objectForKey:wordIndex] == nil)
[myWordArray setObject:[[NSMutableSet alloc] initWithObjects:currentWord, nil] forKey:wordIndex];
else
[[myWordArray objectForKey:wordIndex] addObject:currentWord];
The final intention is to split up an array of words into an array of sets of words grouped by their lengths.
However, I see that [myWordArray count] is 0 after this. Why?
You are confusing the methods of NSMutableDictionary and NSMutableArray: In Objective-C arrays do not have keys but have indexes. If you change the class for myWordArray to NSMutableDicitionary it should work.
Try this, it looks very much like your logic, but (1) it uses NSNumbers as keys, which makes a little more sense, (2) handles the missing set condition more simply, but just adding the set, and (3) breaks up the source lines somewhat for easier debugging...
NSArray *inputStrings = // however these are initialized goes here
NSMutableDictionary *result = [NSMutableDictionary dictionary];
for (NSString *currentString in inputStrings) {
NSInteger currentWordLength = currentString.length;
wordIndex = [NSNumber numberWithInt:currentWordLength];
NSMutableSet *wordSet = [result objectForKey:wordIndex];
if (!wordSet) {
wordSet = [NSMutableSet set];
[result setObject:wordSet forKey:wordIndex];
}
[wordSet addObject:currentWord];
}
If you still have an empty dictionary after running this, it might be simpler to watch what's happening by stepping through it.

Trouble removing NSStrings in NSArray

In an NSArray, I have a 10 values. The values look something like this:
Hello
Hello2
My
My2
Name
Name2
Is
Is2
XcodeDev
XcodeDev2
And I want to delete every second NSString from the NSArray, so I am left with an array like the following. The values are random, and do not have 2 appended to every second one! How can I do this?
Hello
My
Name
Is
XcodeDev
First, you are going to need an instance of NSMutableArray, because NSArrays are immutable and therefore, you cannot change its contents.
NSMutableArray *ary = [NSMutableArray arrayWithArray:anImmutableArray];
Then, you can create an index set that holds all the odd indexes:
NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] init];
for (int i = 1; i < [ary count]; i=i+2) {
[indexSet addIndex:i];
}
Finally, just call removeObjectsAtIndexes: method on the array.
[ary removeObjectsAtIndexes:indexSet];

NSMutableDictionary, alloc, init and reiniting

In the following code:
//anArray is a Array of Dictionary with 5 objs.
//here we init with the first
NSMutableDictionary *anMutableDict = [[NSMutableDictionary alloc] initWithDictionary:[anArray objectAtIndex:0]];
... use of anMutableDict ...
//then want to clear the MutableDict and assign the other dicts that was in the array of dicts
for (int i=1;i<5;i++) {
[anMutableDict removeAllObjects];
[anMutableDict initWithDictionary:[anArray objectAtIndex:i]];
}
Why this crash? How is the right way to clear an nsmutabledict and the assign a new dict?
Thanks guy's.
Marcos.
You do not "reinit" objects — ever. Initialization is meant to be used on a newly alloced instance and might make assumptions that aren't true after initialization is complete. In the case of NSMutableDictionary, you can use setDictionary: to completely replace the contents of the dictionary with a new dictionary or addEntriesFromDictionary: to add the entries from another dictionary (without getting rid of the current entries unless there are conflicts).
More generally, you could just release that dictionary and make a mutableCopy of the dictionary in the array.
If you use an autoreleased dictionary, your code will be a lot simpler:
NSMutableDictionary *anMutableDict = [NSMutableDictionary dictionaryWithDictionary:[anArray objectAtIndex:0]];
... use of anMutableDict ...
for (int i=1; i<5; i++)
{
anMutableDict = [NSMutableDictionary dictionaryWithDictionary:[anArray objectAtIndex:i]];
}
But I don't see the point of that loop you have at the end there.
This isn't how you use init/alloc. Instead, try:
//anArray is a Array of Dictionary with 5 objs.
//here we init with the first
NSMutableDictionary *anMutableDict = [[NSMutableDictionary alloc] initWithDictionary:[anArray objectAtIndex:0]];
... use of anMutableDict ...
//then want to clear the MutableDict and assign the other dicts that was in the array of dicts
for (int i=1;i<5;i++) {
[anMutableDict removeAllObjects];
[anMutableDict addEntriesFromDictionary:[anArray objectAtIndex:i]];
}