Objects in NSMutableArray are all null - objective-c

UIImageView *image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"SudokuCell.png"]];
NSLog(#"%#", image);
[[self.blocks objectAtIndex:row] setObject:image atIndex:col];
NSLog(#"%#", [[self.blocks objectAtIndex:row] objectAtIndex:col]);
Is the code that I'm running. The first NSLog prints a UIImageView object, and the second NSLog prints (null). Why does the second NSLog not print the same thing as the first one?
The array self.blocks is initialized as such:
self.blocks = [[NSMutableArray alloc] initWithCapacity: 9];
for (int i = 0; i < 9; i++)
{
[self.blocks addObject:[[NSMutableArray alloc]initWithCapacity:9]];
}

NSMutableArray doesn't have a setObject:atIndex: method. You should use insertObject:atIndex: instead. Note, that the index can't be higher than the array's count (not the capacity) eg. it won't automatically fill up your array with "empty" values.

Related

All objects in array (interpreted from csv) being returned as the same object (the last object)

What I am trying to achieve, is to convert a csv file into an array of custom objects, however, my attempts at this seem to result in all of the objects in the array being returned as the same object (the last object in the array).
Before I explain further, here is the code:
- (NSArray *)arrayFromCSVFileName:(NSString *)csvFileName fileType:(NSString *)fileType {
// Convert the file into an NSData object
NSString *studentFilePath = [[NSBundle mainBundle] pathForResource:csvFileName ofType:fileType];
NSData *studentData = [NSData dataWithContentsOfFile:studentFilePath];
// Convert the NSData into an NSString
NSString *csvString = [[NSString alloc] initWithData:studentData encoding:NSUTF8StringEncoding];
// Split each record (line) in the csvDataString into an individual array element (split on the newline character \n)
NSArray *csvArray = [csvString componentsSeparatedByString:#"\n"];
// Create an array to hold the parsed CSV data
NSMutableArray *parsedCSVArray = [[NSMutableArray alloc] init];
NSMutableArray *elementArray = [[NSMutableArray alloc] init];
CGSElement *elementToAdd = [[CGSElement alloc] init];
// Loop through each line of the file
for (int i = 0; i < [csvArray count]; i++) {
// Get a reference to this record (line) as a string, and remove any extranous new lines or alike
NSString *csvRecordString = [[csvArray objectAtIndex:i] stringByReplacingOccurrencesOfString:#"\r" withString:#""];
// Split the line by the comma delimeter
NSArray *csvRecordArray = [csvRecordString componentsSeparatedByString:#","];
// Check that there are actually fields (i.e. this is not a blank line)
if ( ([csvRecordArray count] > 0) && ([[csvRecordArray objectAtIndex:0] length] > 0) ) {
elementToAdd.mass = [[csvRecordArray objectAtIndex:1] floatValue];
elementToAdd.atomicNumber = [[csvRecordArray objectAtIndex:0] intValue];
elementToAdd.name = [csvRecordArray objectAtIndex:2];
elementToAdd.symbol = [csvRecordArray objectAtIndex:3];
elementToAdd.period = [[csvRecordArray objectAtIndex:4] intValue];
[elementArray addObject:elementToAdd];
}
}
for (int i = 0; i < [elementArray count]; i++) {
NSLog(#"%i", i);
CGSElement *current = [elementArray objectAtIndex:i];
NSLog(#"Name = %#", current.name);
}
// Return the parsed array
return elementArray;
}
The custom object in question is the CGSElement object, which I am attempting to fill the elementArray with. However, my debug code (the following section of code):
for (int i = 0; i < [elementArray count]; i++) {
NSLog(#"%i", i);
CGSElement *current = [elementArray objectAtIndex:i];
NSLog(#"Name = %#", current.name);
}
Is resulting, rather than in the return of all of the correct element names, it is returning the last element (to put this in context, ununoctium), 118 times.
After some testing, I can safely say that up until after this point:
elementToAdd.mass = [[csvRecordArray objectAtIndex:1] floatValue];
elementToAdd.atomicNumber = [[csvRecordArray objectAtIndex:0] intValue];
elementToAdd.name = [csvRecordArray objectAtIndex:2];
elementToAdd.symbol = [csvRecordArray objectAtIndex:3];
elementToAdd.period = [[csvRecordArray objectAtIndex:4] intValue];
All of the elements are being correctly defined, rather than just the same element over and over.
Needless to say, I'm stumped as to why it would be returning the same object over and over. Any help would be appreciated.
This line:
CGSElement *elementToAdd = [[CGSElement alloc] init];
Should be inside your loop, just before you try to edit the object and add it to the array. Currently you are repeatedly mutating the same object instead of creating new objects for each record.
You add the same entity all the time. It is crated once before the loop and within the loop it values are changed again and angan and it is added to the array. Naturally all items in the aray carry the same values because it is the same object.
If you want then change the array with an NSSet. To a set an object can only added once and you will end up with a set of 1. That is not the solution of couse, it would just visualize what is happening.
To solve it move this line
CGSElement *elementToAdd = [[CGSElement alloc] init];
to the beginning of the body of the for i loop, so that a new instance is created for every iteration and therefore for every index of the array.

NSMutableDictionary containing UIImageViews...Add mutable copy to an NSMutableArray? Alternative?

I'm trying to build words in arrays by their key value in a dictionary. However, it won't work the way I'd like it to, because I can't "copy" a UIImageView.
It would be PERFECT, if when adding the letter from the dictionary to an array, it gives me a copy instead of the real object. I don't want to make multiple images of the same letter and add it to the dictionary, because then I could no longer call it by key "s" or "a", and I need more than one array to use the same letters at at time.
What can I do?
//How I create the letters
char s = 's';
NSString *key = [NSString stringWithFormat:#"%c", s];
alphabetS = [[UIImageView alloc] init]];
[alphabetS setImage:[UIImage imageNamed:#"s.png"]];
[allTilesDictionary setObject:alphabetS forKey:key];
[alphabetS release];
//How I use the imageviews from the dictionary
NSMutableArray *wordOne = [[NSMutableArray alloc] initWithObjects:[allTilesDictionary objectForKey:#"s"],[allTilesDictionary objectForKey:#"h"],[allTilesDictionary objectForKey:#"o"],[allTilesDictionary objectForKey:#"p"], nil];
EDIT: My solution. It works perfectly.
for (UIImageView *letters in wordOne)
{
newLetter = [[UIImageView alloc] init];
newLetter.image = letters.image;
newLetter.userInteractionEnabled = YES;
//I can now either lay them out wherever I want on the view, or add them to a new array.
}
Your original code, slightly modified:
//How I create the letters
char s = 's';
NSString *key = [NSString stringWithFormat:#"%c", s];
[allTilesDictionary setObject:[UIImage imageNamed:#"s.png"] forKey:key];
//How I use the imageviews from the dictionary
NSMutableArray *wordOne = [[NSMutableArray alloc] initWithObjects:[allTilesDictionary objectForKey:#"s"],[allTilesDictionary objectForKey:#"h"],[allTilesDictionary objectForKey:#"o"],[allTilesDictionary objectForKey:#"p"], nil];
Your use of that code, slightly modified:
for (UIImage *letters in wordOne)
{
newLetter = [[UIImageView alloc] init];
newLetter.image = letters;
newLetter.userInteractionEnabled = YES;
//I can now either lay them out wherever I want on the view, or add them to a new array.
}
No unnecessary UIImageViews created.
for (UIImageView *letters in wordOne)
{
newLetter = [[UIImageView alloc] init];
newLetter.image = letters.image;
newLetter.userInteractionEnabled = YES;
//I can now either lay them out wherever I want on the view, or add them to a new array.
}

Method Creates an Array with 11 objects, All Out of Scope, Unrecognized Selector Results

Okay, so, I'm doing a simple lookup. I have an array of NSString objects and a string to search for in the array's elements.
It all seems to work up until I try to add a match to a new mutable array made to hold the search results. The stringHolder variable gets the string, and resultsCollectorArray even get the right number of new elements, but each element is empty and "out of range". Here's the method:
#implementation NSArray (checkForString)
-(NSMutableArray *) checkForString: (NSString *) matchSought
{
long unsigned numberofArrayElements;
long unsigned loop = 0;
NSRange searchResults;
NSMutableArray * resultCollectorArray = [[NSMutableSet alloc] init];
id stringHolder;
numberofArrayElements = [self count];
while (loop < numberofArrayElements) {
searchResults.length = 0;
searchResults = [[self objectAtIndex: loop] rangeOfString: matchSought options:NSCaseInsensitiveSearch];
if (searchResults.length > 0) {
stringHolder = [self objectAtIndex: loop];
[resultCollectorArray addObject: stringHolder];
}
loop++;
}
return [resultCollectorArray autorelease];
}
Once we get back to the main portion of the program, I get an unrecognized selector sent to the mutable array that was supposed to receive the result of the method. Here's the main section:
#import <Foundation/Foundation.h>
#import "LookupInArray.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *testString = [[NSString alloc] initWithString: #"ab"];
NSMutableString * resultString = [[NSString alloc] init];
NSArray * theArray = [[NSArray alloc] initWithObjects: ..., nil]; // Actual code has the objects
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
NSUInteger arrayCount = 0;
unsigned long loops = 0;
resultArray = [theArray checkForString: testString];
arrayCount = [resultArray count];
while (loops < arrayCount){
resultString = [resultArray objectAtIndex: loops]; // Here's where we get the unrecognized selector.
NSLog(#"%#", resultString);
loops++;
}
[pool drain]; // Also, I'll release the objects later. I just want to get what's above working first.
return 0;
}
I've searched the other answers (for hours now), but didn't seen anything that solved the issue.
Any and all help would be really appreciated.
And thanks beforehand.
NSMutableArray * resultCollectorArray = [[NSMutableSet alloc] init]; is so incorrect. You are creating a mutable set and assigning it to a mutable array.
You are getting unrecognized selector because objectAtIndex: is not a valid selector for NSMutableSet. Make that statement,
NSMutableArray * resultCollectorArray = [[NSMutableArray alloc] init];
A Better way
NSArray * filteredArray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF contains[cd] %#", searchString]];
You can directly filter the array using predicates. This way you do this in a single step. :)

NSMutableArray not retaining?

I'm having some issues with my Arrays, I hoped anyone here can tell me what I'm doing wrong.
I have 3 arrays: tmpAnswersArray, localAnswersArray & finalAnswersArray.
I also have a method to shuffle a given array in the same class.
The first NSLog shows the count for the localAnswersArray is 6 (how it supposed to be).
The third NSLog shows the localAnswersArray count is 0, even though I didn't change anything in that array.
localAnswersArray = [[NSMutableArray alloc] init];
localAnswersArray = [self shuffleArray:tmpAnswersArray];
[tmpAnswersArray release];
NSLog(#"Shuffled localAnswersArray (count = %d) & removed tmpAnswersArray",[localAnswersArray count]);
finalAnswersArray = [[NSMutableArray alloc] init];
NSLog(#"init finalAnswersArray");
for (int arrayCount = 0; arrayCount < 6; arrayCount++) {
NSLog(#"TEST ---> %d",[localAnswersArray count]);
[finalAnswersArray addObject:[localAnswersArray objectAtIndex:arrayCount]];
}
Is the first line of this code also retains the array?
Do I have to retain it manually somehow?
Why is the array count drops to 0 all of a sudden?
Thanks for any help!
You need to review the Memory Management Guidelines.
localAnswersArray = [[NSMutableArray alloc] init];
localAnswersArray = [self shuffleArray:tmpAnswersArray];
You create an array (that you own), then immediately replace it with a different array.
And it would seem that your entire block of code could be replaced with this:
finalAnswersArray = [[self shuffleArray:tmpAnswersArray] mutableCopy];

Size of the NSMutable Array in objective C?

I want to ask the size of the NSMutable Array can be 2000? If not, is it possible to open an array to store 2000 elements. The elements is the user-defined object. Thank you.
The answer is that an NSMutableArray always starts with a size of zero. If you want it to be so you can do something like this:
NSMutableArray* anArray = [NSMutableArray arrayWithSize: 2000];
[anArray replaceObjectAtIndex: 1999 withObject: foo];
you need to prefill the array with NSNull objects e.g.
#implementation NSArray(MyArrayCategory)
+(NSMutableArray*) arrayWithSize: (NSUInteger) size
{
NSMutableArray* ret = [[NSMutableArray alloc] initWithCapacity: size];
for (size_t i = 0 ; i < size ; i++)
{
[ret addObject: [NSNull null]];
}
return [ret autorelease];
}
#end
Edit: some further clarification:
-initWithCapacity: provides a hint to the run time about how big you think the array might be. The run time is under no obligation to actually allocate that amount of memory straight away.
NSMutableArray* foo = [[NSMutableArray alloc] initWithCapacity: 1000000];
NSLog(#"foo count = %ld", (long) [foo count]);
will log a count of 0.
-initWithCapacity: does not limit the size of an array:
NSMutableArray* foo = [[NSMutableArray alloc] initWithCapacity: 1];
[foo addObject: #"one"];
[foo addObject: #"two"];
doesn't cause an error.