NSMutablearray doesn't prints all array elements - ios

I'm using the following piece of code to store elements in array dynamically and retrieve it later
for (int i = 0; i< [companyNames count]; i++){
testimonialsArray = [[NSMutableArray alloc]init];
testimonialsComplementedArray = [[NSMutableArray alloc]init];
[testimonialsArray addObject:companyNames[i] ];
[testimonialsComplementedArray addObject:texts[i]];
NSLog(#"Compliments %#",testimonialsComplementedArray);
}
But it prints only the last copy that had been added to the array. How to retrieve all elements?
Following are the company names,
"General Marketing Company",
"United Enterprises, Chennai",
"Hari Match Industries"

allocate the testimonialsArray = [[NSMutableArray alloc]init]; in above the for loop if you initilize in inside the loop every time the memory will be initilize, so final value only you get on output in finally , do like
testimonialsArray = [[NSMutableArray alloc]init];
testimonialsComplementedArray = [[NSMutableArray alloc]init]
for (int i = 0; i< [companyNames count]; i++){
[testimonialsArray addObject:companyNames[i] ];
[testimonialsComplementedArray addObject:texts[i]];
}
NSLog(#"Compliments %#",testimonialsComplementedArray);

testimonialsArray = [[NSMutableArray alloc]init]; // have to init out side the loop
testimonialsComplementedArray = [[NSMutableArray alloc]init]; // have to init out side the loop
for (int i = 0; i< [companyNames count]; i++){
[testimonialsArray addObject:companyNames[i] ];
[testimonialsComplementedArray addObject:texts[i]];
}
NSLog(#"Compliments %#",testimonialsComplementedArray);

You are allocating mutable array every time in for loop because of that its initializes array and add object in that everytime.Always its better to alloc any object in ViewDidLoad method.

Try like this.
testimonialsArray = [[NSMutableArray alloc]init];
testimonialsComplementedArray = [[NSMutableArray alloc]init];
for (int i = 0; i< [companyNames count]; i++){
[testimonialsArray addObject:companyNames[i] ];
[testimonialsComplementedArray addObject:texts[i]];
}
NSLog(#"Compliments %#",testimonialsComplementedArray);

Related

What is the default capacity of NSMutableDictionary?

Basically when you call
[[NSMutableDictionary alloc] init];
Apple will create a dictionary of some default size. What is that default size?
Interestingly, on iOS at least it appears that Apple does the same thing for init as if it were initWithCapacity:0. I ran the following code under Instruments:
int max=1000000;
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:max];
for(int i=0; i < max; i++) {
[array addObject:[[NSMutableDictionary alloc] init]];
}
if(true) return array; // Don't let the compiler remove the ref
Next I did something very similar but with 0 capacity explicitly specified:
int max=1000000;
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:max];
for(int i=0; i < max; i++) {
[array addObject:[[NSMutableDictionary alloc] initWithCapacity:0]];
}
if(true) return array; // Don't let the compiler remove the ref
Both of these ran with a max consumption of 55.3 MB on my iOS 9 device. Then I tried using initWithCapacity:1 when creating the dictionaries:
int max=1000000;
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:max];
for(int i=0; i < max; i++) {
[array addObject:[[NSMutableDictionary alloc] initWithCapacity:1]];
}
if(true) return array; // Don't let the compiler remove the ref
In that case my max consumption was 116.4 MB.
As other commenters have noted, this may vary from OS to OS and even from version to version. Don't rely on it, but that's one way to tell what NSMutableDictionary init is doing.

nsmutableArray replacing element with last added object

After adding new element in mutableArray previously added element(Fetched from dictionary) is also replace with newly added element.
for (int i = 0; i < [_ContentArray count]; i++){
if ([[[_ContentArray objectAtIndex:i]objectForKey:#"type"] isEqualToString:#"video"]) {
NSString *videoUrl = [[_ContentArray objectAtIndex:i]objectForKey:#"url"];
NSString *videoName = [[_ContentArray objectAtIndex:i]objectForKey:#"title"];
[_videoContentDict setValue:videoUrl forKey:#"url"];
[_videoContentDict setValue:videoName forKey:#"title"];
[_videoArray addObject:_videoContentDict];
NSLog(#"%#%%",_videoArray);
}
}
HERE -
_videoContentDict is an mutableDictionary
_videoArray is an mutableArray
I think you get each time old object with new object in to the NSMutableArray. because you are allocated NSMutableDictionary outside the for loop.
So make your NSMutableDictionary alloc init in side the for loop like following code:
for (int i = 0; i < [_ContentArray count]; i++){
if ([[[_ContentArray objectAtIndex:i]objectForKey:#"type"] isEqualToString:#"video"]) {
_videoContentDict = [[NSMutableDictionary alloc]init];
NSString *videoUrl = [[_ContentArray objectAtIndex:i]objectForKey:#"url"];
NSString *videoName = [[_ContentArray objectAtIndex:i]objectForKey:#"title"];
[_videoContentDict setValue:videoUrl forKey:#"url"];
[_videoContentDict setValue:videoName forKey:#"title"];
[_videoArray addObject:_videoContentDict];
NSLog(#"%#%%",_videoArray);
}
}

How to save two Arrays in two dimensional Array?

I am new at iOS Dev. I want to save two different arrays (array1 & array2) in 2 dimensional array. I know how to save data directly in two dimensional array but can't by save two different arrays in one.
NSString* path = [[NSBundle mainBundle] pathForResource:#"Aasvogel" ofType:#"txt"];
NSString* content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
NSArray* foo = [content componentsSeparatedByString: #","];
NSMutableArray *array1 = #[], *array2 = #[];
for ( int i = 0; i < [foo count]; i++ )
{
NSString* day = foo[i];
if ( i % 2 == 0 ) { [array1 addObject:day];}
else { [array2 addObject:day];}
}
// and here i have populated two arrays (array1 and array2)
// Now i want to save these arraya in below two dimensional array (dataArray) atIndex:0 and at Index:1
NSMutableArray *dataArray = [[NSMutableArray alloc] initWithCapacity: 2];
[dataArray addObject:[NSMutableArray arrayWithObjects:#"e",
#"el",
#"ale",
#"vela",
#"gavel",nil] atIndex:0];
[dataArray addObject:[NSMutableArray arrayWithObjects:#"Represents 50 in Roman numeral",
#"Building Wing",
#"Pub Brew",
#"Thin Parchment or membranes",
#"chairperson's hammer",nil] atIndex:1];
I have recently implemented 2D array into my application. Please check below code which is available at 2DArray
int capacity;
#property (nonatomic, strong) NSMutableArray *outerArray;
#define kCRL2DArrayEmptyKey #"kCRL2DArrayEmptyKey"
- (id) initWithRows:(int)x columns:(int)y
{
if (self = [super init])
{
capacity = y;
self.outerArray = [NSMutableArray array];
for (int i = 0; i < x; i++) {
NSMutableArray *innerArray = [NSMutableArray array];
for (int j = 0; j < y; j++) {
[innerArray addObject:kCRL2DArrayEmptyKey];
}
[self.outerArray addObject:innerArray];
}
}
return self;
}
you can try this
NSArray * firstArray, *secondArray;
NSArray * mainArray= [[NSArray alloc]initWithObjects: firstArray, secondArray, nil];
I am not sure about 2-dimensional array in iOS but if I were you I would be saved the two arrays within a dictionary such as
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
[dict setvalue:yourArray forKey:#"FirstArray"];
[dict setvalue:yourSecondArray forKey:#"SecondArray"];
And Use it accordingly.
There’s no such thing as a two (or more) dimensional NSArray. If you genuinely need an n-dimensional array object in iOS or OS X, you can of course roll your own, or you could instead create an NSArray of NSArray instances (which are columns and which are rows is entirely up to you). In that case, you could e.g. add items by doing
[[outerArray objectAtIndex:0] addObject:#"Foo"];
[[outerArray objectAtIndex:1] addObject:#"Bar"];
That said, for the problem you are tackling, it looks to me as if an NSDictionary might be more appropriate, e.g. with keys #"e", #"el" and values #"Represents 50 in Roman numerals", #"Building Wing".
If your concern is that the keys of NSDictionary are not held in sorted order, you can always extract the keys as an array and sort them. Or, if the keys change regularly, you might want to use a more sophisticated approach (e.g. keeping a separate sorted array of keys and inserting them into the right place when adding to the NSDictionary).
Also, you know that in modern Objective-C you can write e.g.
#[ #"a", #"b", #"c" ]
or
#{ #"a": #1, #"b": 2 }
rather than the very verbose forms you're using above?
this is how u add anything in a 2d array i.e an Array of arrays in objective-c
NSMutableArray *array 1 = [[NSMutableArray alloc]init];
NSMutableArray *array 2;
for(int col = 0;col <5;col++){
array2 = [[NSMutableArray alloc]init];
for(int row = 0;row<5;row++){
[array2 addObject:myItems];
}
[array1 addObject:array2];
}
hope this helps
use for loop to generate 2d array from 2 different array,
follow this stracture
int i, j;
for(i = 0; i < nrows; i++)
{
for(j = 0; j < ncolumns; j++)
array[i][j] = 0;
}
}
May be it will help you

Trying to create an array of dictionaries, keep getting the same dictionary repeated in the array

I'm trying to use NSData to pull information out of a text file, and then load it into a dictionary.
First I create a string of the text file, and load each record into an array.
Then I break apart the each record into individual data elements.
The problem I'm having is that when the dictionary is fully populated, I then use addObject to load it into the array, which it does do successfully. The problem is that when the next loop creates a new dictionary, the same dictionary gets loaded into the array, and I end up an array of all the same dictionaries, instead of multiple different dictionary objects.
I'm guessing there is some simple mistake I'm making that is causing this error. Any help would be appreciated.
NSString *clientListFile = [NSURL URLWithString: #"/textfile"];
NSData *clientListDataFile = [NSData dataWithContentsOfFile:clientListFile];
NSString *clientListString = [[NSString alloc]initWithBytes:[clientListDataFile bytes] length:[clientListDataFile length] encoding:NSUTF8StringEncoding];
NSString *returnDelimiter = #"\n";
NSString *commaDelimiter = #",";
NSString *exclamationDelimiter = #"!";
NSArray *keysAndObjects = [[NSArray alloc]init];
NSMutableDictionary *clientList = [[NSMutableDictionary alloc]init];
NSMutableArray *clientListOfDictionaries = [[NSMutableArray alloc]init];
NSArray *sentenceArray = [clientListString componentsSeparatedByString:returnDelimiter];
for (int i = 0; i < [sentenceArray count]; i=i+1) {
[clientList removeAllObjects]; //to start with a fresh dictionary for the next iteration
NSString *recordSentence = [sentenceArray objectAtIndex:i];
NSArray *attributes = [recordSentence componentsSeparatedByString:commaDelimiter];
for (int j = 0; j < [attributes count]; j = j+1) {
NSString *pairsOfItems = [attributes objectAtIndex:j];
//a small arry, of only two objects, the first is the key, the second is the object
keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
[clientList setObject:[keysAndObjects lastObject] forKey:[keysAndObjects firstObject]];
}
[clientListOfDictionaries addObject:clientList];
}
When I used NSLog to see what's in the dictionary, I mulitple objects of the same dictionary repeated, even though up earlier in the iteration, I can see that the code is creating separate and unique dictionaries.
Instead of this line
[clientListOfDictionaries addObject:clientList];
you can have
[clientListOfDictionaries addObject:[[NSArray alloc] initWithArray:clientList];
That way you will be adding new arrays to clientListOfDictionaries instead of the same one.
Move this line:
NSMutableDictionary *clientList = [[NSMutableDictionary alloc]init];
to just after the first for loop line and then delete the line:
[clientList removeAllObjects];
It's important to create a new dictionary for each iteration.
You should also delete the following line:
NSArray *keysAndObjects = [[NSArray alloc]init];
and change:
keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
to:
NSArray *keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
You are allocated and initialising your clientList dictionary outside of the for loop, so you only have one dictionary, which you are storing in your array multiple times. Adding the dictionary to the array does not copy it, it merely adds a pointer to the object.
you need to move
NSMutableDictionary *clientList = [[NSMutableDictionary alloc]init];
inside your first for loop in place of
[clientList removeAllObjects];
Also, componentsSeparatedByString: returns an NSArray, so you don't need to allocate and initialise one. You can simply define the variable -
NSArray *keysAndObjects;
Because you're using the same clientList variable for each iteration of the loop. You need to create a whole new dictionary object each time.
Try this modified code:
NSData *clientListDataFile = [NSData dataWithContentsOfFile:clientListFile];
NSString *clientListString = [[NSString alloc]initWithBytes:[clientListDataFile bytes] length:[clientListDataFile length] encoding:NSUTF8StringEncoding];
NSString *returnDelimiter = #"\n";
NSString *commaDelimiter = #",";
NSString *exclamationDelimiter = #"!";
NSArray *keysAndObjects = nil;
NSMutableArray *clientListOfDictionaries = [[NSMutableArray alloc] init];
NSArray *sentenceArray = [clientListString componentsSeparatedByString:returnDelimiter];
for (NSUInteger i = 0; i < [sentenceArray count]; ++i) {
NSMutableDictionary *clientList = [[NSMutableDictionary alloc] init]; //to start with a fresh dictionary for the next iteration
NSString *recordSentence = [sentenceArray objectAtIndex:i];
NSArray *attributes = [recordSentence componentsSeparatedByString:commaDelimiter];
for (NSUInteger j = 0; j < [attributes count]; ++j) {
NSString *pairsOfItems = [attributes objectAtIndex:j];
//a small arry, of only two objects, the first is the key, the second is the object
keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
[clientList setObject:[keysAndObjects lastObject] forKey:[keysAndObjects firstObject]];
}
[clientListOfDictionaries addObject:clientList];
}
An alternate option, though likely less efficient, is to to change the line:
[clientListOfDictionaries addObject:clientList];
to
[clientListOfDictionaries addObject:[clientList copy]];
That lets you keep using the same clientList variable, since you're adding a copy of it to the clientListOfDictionaries array. I just point that out because it might help you understand what's going on.
Also, note that I changed this line for you:
NSArray *keysAndObjects = [[NSArray alloc]init];
to
NSArray *keysAndObjects = nil;
Because it's just a pointer that is set by your call to componentsSeparatedByString, you don't need to allocate an array for it. That array will just vanish in your first iteration of the loop.
Should be added the new dictionary to array. Otherwise it will not add to an array. Every object in array have same dictionary mapping. So it will give you the same dictionary value. Create new dictionary for every object and add to array.
for (int i = 0; i < [sentenceArray count]; i=i+1) {
NSMutableDictionary *clientList = [[NSMutableDictionary alloc]init];
NSString *recordSentence = [sentenceArray objectAtIndex:i];
NSArray *attributes = [recordSentence componentsSeparatedByString:commaDelimiter];
for (int j = 0; j < [attributes count]; j = j+1) {
NSString *pairsOfItems = [attributes objectAtIndex:j];
//a small arry, of only two objects, the first is the key, the second is the object
NSArray *keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
[clientList setObject:[keysAndObjects lastObject] forKey:[keysAndObjects firstObject]];
}
[clientListOfDictionaries addObject:clientList];
}

My method won't work

I'm a total noob and need help with a method I'm writing.
The method creates a deck of cards (using NSMutableArray). I'm first experimenting with loading the array with numbers 1-13 randomly (each number appearing once).
When I run a simple test program to print the values in the array, I get a "Build Successful" but an error once the program starts. The error says "[__NSArrayM insertObject:atIndex:]: object cannot be nil".
Once I understand what I'm doing wrong, I can then expand on the method properly. Thanks!
NB: This is my first post. Is this type of question ok?
- (void) createDeck {
int r;
BOOL same;
deck = [[NSMutableArray alloc]init];
NSNumber *randNum;// = nil;
randNum = [[NSNumber alloc]init];
[randNum initWithInt: (arc4random()%13)+1];
[deck addObject: randNum]; // First card added to deck
same = FALSE;
while (!same) {
for (int i=1; i<13; i++) {
same = FALSE;
for (r=0; r<=i; r++) {
[randNum initWithInt: (arc4random()%13)+1];
if ([deck objectAtIndex:r] == [deck objectAtIndex:i]) {
same = TRUE;
}
[deck addObject: randNum]; // Next card added to deck
}
}
}
}
you cannot re-init randNum:
NSNumber *randNum;// = nil;
randNum = [[NSNumber alloc]init];
[randNum initWithInt: (arc4random()%13)+1];
and the third line is missing the assignment anyway. just do:
NSNumber *randNum = [[NSNumber alloc] initWithInt:(arc4random()%13)+1];
and put that inside the inner for loop, like this:
BOOL same = FALSE;
NSMutableArray *deck = [[NSMutableArray alloc] initWithCapacity:13];
[deck addObject:[[NSNumber alloc] initWithInt:(arc4random()%13)+1]]; // First card added to deck
while (!same) {
for (int i = 1; i < 13; i++) {
same = FALSE;
for (int r = 0; r <= i; r++) {
NSNumber *randNum = [randNum initWithInt:(arc4random()%13)+1]; // modern ObjC will assign a register for this outside the while loop, but restrict the variable's scope to the inner-most loop
if ([deck objectAtIndex:r] == [deck objectAtIndex:i])
same = TRUE;
[deck addObject: randNum]; // Next card added to deck
}
}
Note that I haven't thought through the logic of what you are trying to do here, I've only attempted to resolve the NULL object reference. The error was referring to the first line [deck addObject: randNum] outside of the loop.
Try to use this line of code where you using NSNumber
NSNumber * randNum = [NSNumber numberWithInt: (arc4random%13)+1];
Instead of
[[NSNumber alloc] initWithInt: ]

Resources