I have an array which I store different classes which again hold different arrays. All arrays are defined as NSMutabelArrays.
When I want to delete an object in an array, my app crashes. This is my code:
NSLog(#"string to be deleted:%#", [[[self.myLibrary objectAtIndex:self.currentNoteBookNumber] tabReference] objectAtIndex:tid]);
NSLog(#"string to be deleted:%#", [[[self.myLibrary objectAtIndex:self.currentNoteBookNumber] tabColours] objectAtIndex:tid]);
NSLog(#"string to be deleted:%#", [[[self.myLibrary objectAtIndex:self.currentNoteBookNumber] tabTitles] objectAtIndex:tid]);
[[[self.myLibrary objectAtIndex:self.currentNoteBookNumber] tabReference] removeObjectAtIndex:tid];
[[[self.myLibrary objectAtIndex:self.currentNoteBookNumber] tabColours] removeObjectAtIndex:tid];
[[[self.myLibrary objectAtIndex:self.currentNoteBookNumber] tabTitles] removeObjectAtIndex:tid];
And this is the console output:
2011-05-01 22:03:40.788 M[61452:207] string to be deleted:2
2011-05-01 22:03:40.789 M[61452:207] string to be deleted:Orange
2011-05-01 22:03:40.791 M[61452:207] string to be deleted:Art
2011-05-01 22:03:40.806 M[61452:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSMutableArray objectAtIndex:]: index 0 beyond bounds for empty array'
I don't really know what I'm doing wrong. There is obviously something in the array, so it shouldn't be 0. I mean it is the ONLY thing stored in the array at the moment, but that shouldn't be a problem, I guess?
I'd be very grateful for any help on this.
EDIT:
I think I haven't provided enough code. This is the method in which I set up myLibrary:
-(void) setupLibrary {
myLibrary = [[NSMutableArray alloc] init];
NoteBook *newNoteBook = [[NoteBook alloc] init];
newNoteBook.titleName = #"TEST";
NSMutableArray *ttArray = [[NSMutableArray alloc] init];
[ttArray addObject:#"Art"];
NSMutableArray *tcArray = [[NSMutableArray alloc] init];
[tcArray addObject:#"Orange"];
NSMutableArray *trArray = [[NSMutableArray alloc] init];
[trArray addObject: [NSNumber numberWithInteger:2]];
newNoteBook.tabTitles = ttArray;
newNoteBook.tabColours = tcArray;
newNoteBook.tabReference = trArray;
[myLibrary addObject:newNoteBook];
currentNoteBookNumber = 0;
[newNoteBook release];
[ttArray release];
[tcArray release];
[trArray release];
}
Now it appears that if I delete, for instance, one object in the tabTitles array (e.g. "Art"), I delete the entire newNoteBook object. I.e. once I delete a string in tabTitles, all other strings at the same position in tabColours or tabReference will be deleted as well. Why is this so?
The following code will crash after I successfully deleted the string # position 0 in an array in my class which is stored in another array:
NSLog(#"string deleted:%#", [[[self.myLibrary objectAtIndex:0] tabReference] objectAtIndex:0]);
[[[self.myLibrary objectAtIndex:0] tabReference] removeObjectAtIndex:0];
NSLog(#"string deleted:%#", [[[self.myLibrary objectAtIndex:0] tabColours] objectAtIndex:0]);
[[[self.myLibrary objectAtIndex:0] tabColours] removeObjectAtIndex:0];
Don't know what's the problem here, but you should consider to keep your arrays safe:
if([yourArray count] > tid) {
[yourArray removeObjectAtIndex.tid;
}
Your error
-[NSMutableArray objectAtIndex:]: index 0
is telling that you are trying to get an object at index 0 not that you want to remove it. So I think what you did is you called the method where you have your reading and removing code 2 times in a row. Try to see it that is the case.
Related
i have the following line of code
NSMutableArray *marray = [[NSArray arrayWithObjects: #"4", #"1", #"9", nil]mutableCopy];
and i want to replace it with the following line
NSMutableArray *marray = [[NSMutableArray alloc]initWithArray:garr];
where garr is global array from global method
the problem is that the code works fine when calling the first line but when using the second one the code crash , appreciate ur help and ideas thanks , iknow that the first one is NSArray but the garr variable source is NSMutable array
here is the code for garr
garr = [[NSMutableArray alloc]init];
for (int x = 0; x < 10; x++) {
[garr addObject:[NSNumber numberWithInt: arc4random()%200]];
here is the error msg
console error:2012-09-02 14:46:42.976 sort_alg[1561:207] -[NSCFNumber UTF8String]: unrecognized selector sent to instance 0x4b1a170 2012-09-02 14:46:42.978 sort_alg[1561:207] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFNumber UTF8String]: unrecognized selector sent to instance 0x4b1a170' * Call stack at first throw: –
this is the code that generates the end value
NSString *element;
NSEnumerator *iterator = [marray objectEnumerator];
while ((element = [iterator nextObject]) != nil)
printf("%s ", [element UTF8String]);
printf("\n");
[marray release]; // array needs to be released!
[pool release];
thanks
Problem lies in printf("%s ", [element UTF8String]);.
NSNumber has no UTF8String method, only a stringValue. You can't printf it either, but you can NSLog("%#", [element stringValue]), or NSLog("%d", [element intValue]) if you know it's an int.
Please have a look on my code which i am using to add dynamic cells in my table view add run time. At did select of my table view i have called this method.
- (void) allServersFound
{
// called from delegate when bonjourservices has listings of machines:
NSArray *newPosts = [[NSArray alloc]initWithObjects:#"A", nil]; // NSArray of machine names;
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithObjects: #"A",#"B",#"C",#"D", nil];
int i = 0;
for (NSArray *count in newPosts)
{
[tempArray addObject:[NSIndexPath indexPathForRow:i++ inSection:0]];
}
[[self tblHome] beginUpdates];
[[self tblHome] insertRowsAtIndexPaths:tempArray withRowAnimation:UITableViewRowAnimationNone];
[[self tblHome] endUpdates];
[tempArray release];
}
But this give me following Exception at run time:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSIndexPath _fastCStringContents:]: unrecognized selector sent to instance 0x4e0e130
First you initialize your tempArray with strings like this:
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithObjects: #"A",#"B",#"C",#"D", nil];
Then you add indexPaths like this:
[tempArray addObject:[NSIndexPath indexPathForRow:i++ inSection:0]];
so the array you pass to the insertRowsAtIndexPaths method contains both strings and indexPaths objects. I think this is the reason of the exception.
As others noted, your tempArray contains a mixture of NSString and NSIndexPath objects. This is the most obvious thing that you need to address before you do anything else. You can use [NSMutableArray array] class method for that (it's autoreleased, so you'll need to remove the call to [tempArray release] at the end of your method).
A less obvious thing is that the model of your UITableView must be updated before you call insertRowsAtIndexPaths, otherwise you would get another exception in a much less obvious place.
Your tmparray contains NSString values as well as the IndexPaths, try removing the NSStrings first.
Try replacing the line
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithObjects: #"A",#"B",#"C",#"D", nil];
with the line
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithObjects:nil];
I've got a problem. I'm trying to sort the items from 1 array (name: mps) into an other array (name: totalArray), but every item should be in a new array. In short: the items in mps should move into a new array, but every item should be in a new array, so the totalArray is an array of arrays. After that, totalArray should be copied back into mps.
To clarify, here is the code:
NSMutableString *oud = [[NSMutableString alloc] init];
NSMutableString *nieuw = [[NSMutableString alloc] init];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
[tempArray removeAllObjects];
NSMutableArray *totalArray = [[NSMutableArray alloc] init];
[totalArray removeAllObjects];
tempArray = [[NSMutableArray alloc] init];
[tempArray removeAllObjects];
for (int j = 0; j < [mps count]; j++)
{
nieuw = [[mps objectAtIndex:j] valueForKey:#"ConfigurationAlias"];
if (j != 0)
{
if ([oud rangeOfString:nieuw].location == NSNotFound)
{
NSLog(#"ADDED!");
[totalArray addObjectsFromArray:tempArray];
[oud setString:nieuw];
[tempArray removeAllObjects];
[tempArray addObject:[mps objectAtIndex:j]];
}
else
{
[tempArray addObject:[mps objectAtIndex:j]];
}
}
else {
[oud setString:nieuw];
[tempArray addObject:[mps objectAtIndex:j]];
}
}
//En de array weer laden in de tabel
//NSLog(#"%#", totalArray);
NSLog(#"%i", [mps count]);
[mps removeAllObjects];
NSLog(#"REMOVED!!!");
NSLog(#"%i", [mps count]);
[mps addObjectsFromArray:totalArray];
NSLog(#"Added totalArray: %i", [totalArray count]);
NSLog(#"%i", [mps count]);
[tempArray release];
[totalArray release];
[tabelView reloadData];
}
Now, here comes my problem:
The log gives the line 2011-04-07 10:02:46.368 Fleet Manager[901:40b] ADDED! 11 times, then it posts 16 (mps count, this is correct), then the line REMOVED!, then 0 (mps count, also correct), but then the line: Added totalArray: 15. This can't be correct, it added 11 times but it counts 15?
This a problem for me, in the first place because it's plain incorrect, but the tableview gets screwed up as well because of the section-amount not being correct either (15 sections). Anybody has any idea what's going on?
EDIT: all the objects in mps are dictionaries, and all of them have a value for the key "ConfigurationAlias".
First, I would like to suggest using debugging mode instead of bunch of NSLog functions to track down what's actually happening inside your objects and variables. Try using breakpoints. Set one for [totalArray addObjectsFromArray:tempArray]; line so every time this line of code is reached the execution would stop and let you look around, check different fields' states inside totalArray and tempArray objects.
Concerning your problem... Since you are using addObjectsFromArray: that means that passed array may pass not one but several objects (thus the plural in method name). I guess one of those "11 times" added more than one element - that should explain the actual count being more than the times you've called this method. Again, please check tempArray contents.
Good luck!
If you want to end up with an array of arrays, you need to be allocating temp arrays inside the loop. It also seems like you are overdoing it with clearing out the arrays.
It appears you are trying to add the value from mps to totalArray regardless of the conditions, so it would make sense to only do that in one place (outside of the conditions).
Also, if you are not mutating the arrays (such as tempArray), you can use NSArray instead, which should be smaller and faster.
Finally, you should be able to assign the new array to mps instead of doing the expensive array copying. Not sure if that is somehow referenced as the table delegate, though.
I would try something like:
NSMutableString *oud = [[NSMutableString alloc] init];
NSMutableString *nieuw = [[NSMutableString alloc] init];
NSMutableArray *tempArray;
NSMutableArray *totalArray = [[NSMutableArray alloc] init];
for (int j = 0; j < [mps count]; j++)
{
tempArray = [[NSMutableArray alloc] init];
[totalArray addObject:tempArray];
[tempArray release];
nieuw = [[mps objectAtIndex:j] valueForKey:#"ConfigurationAlias"];
if (j != 0)
{
if ([oud rangeOfString:nieuw].location == NSNotFound)
{
NSLog(#"ADDED!");
[oud setString:nieuw];
}
}
else {
[oud setString:nieuw];
}
}
NSLog(#"%i", [mps count]);
[mps removeAllObjects];
NSLog(#"REMOVED!!!");
NSLog(#"%i", [mps count]);
[mps addObjectsFromArray:totalArray];
NSLog(#"Added totalArray: %i", [totalArray count]);
NSLog(#"%i", [mps count]);
[totalArray release];
[tabelView reloadData];
}
You should
sort the base array in a tempArray
create an empty resultArray
iterate through tempArray and for each item create an itemArray containing the item on the first position and add this array to resutArray
don't forget to release all alloc-ed temporary data
Check this out for sorting easily: Sorting arrays via Apple
I have a method with the following code:
NSMutableArray *pickerArray = [[NSMutableArray alloc] init];
int i;
for(i = 1; i <= 7; i++) {
NSString *myString = [NSString stringWithFormat:#"%#", i];
[pickerArray addObject:myString];
}
for(i = 1; i <= 7; i++) {
NSString *fieldName = [[NSString alloc] initWithFormat:#"column%d", i];
[self setValue:pickerArray forKey:fieldName]; // setValue or initWithArray ???
[fieldName release];
[pickerArray release];
}
srandom(time(NULL));
When I build the application everything builds correctly but it crashes on start in the console i get the following error:
* -[NSCFString superview]: unrecognized selector sent to instance 0x380da90
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFString superview]: unrecognized selector sent to instance 0x380da90'
If instead of using an array containing strings I use UIImageView containing UIImages then everything works correctly...
I only would like to populate my picker with an array of numbers from 1 to 50...
Any help would be really appreciated... this thing is driving me mad :)
I don't think you want [myString release]; in your first for loop as the string you create is auto-released (rule of thumb, anything that is created without alloc, init, or new is auto-released)
Problem solved.... was something to do with the number of element in the pickerview, nothing to do with the method itself! Thanks anyway!
I'm trying to create an array (States) of arrays (Cities). Whenever I try to add an item to my City array I get this error:
'NSInvalidArgumentException', reason: '*** +[NSMutableArray
addObject:]: unrecognized selector sent to class 0x303097a0
My code is as follows.
The line it errors on is
[currentCities addObject:city];
I'm sure I've got some Memory Management problem as I still don't understand it all that well. Was hoping someone could explain my mistake to me.
if (sqlite3_prepare_v2(db, sql, -1, &statement, NULL) == SQLITE_OK){
// We need to keep track of the state we are on
NSString *state = #"none";
NSMutableArray *currentCities = [NSMutableArray alloc];
// We "step" through the results - once for each row
while (sqlite3_step(statement) == SQLITE_ROW){
// The second parameter indicates the column index into the result set.
int primaryKey = sqlite3_column_int(statement, 0);
City *city = [[City alloc] initWithPrimaryKey:primaryKey database:db];
if (![state isEqualToString:city.state])
{
// We switched states
state = [[NSString alloc] initWithString:city.state];
// Add the old array to the states array
[self.states addObject:currentCities];
// set up a new cities array
currentCities = [NSMutableArray init];
}
[currentCities addObject:city];
[city release];
}
}
The lines:
// set up a new cities array
currentCities = [NSMutableArray init];
Should read:
// set up a new cities array
[currentCities init];
which should hopefully fix your problem. Instead of initializing your array, you're sending an init message to a class object, which doesn't do anything. Afterwards, you're currentCities pointer is still not initialized.
Even better would be to remove that line and change the 4th line such that you allocate and initialize all in one step:
NSMutableArray *currentCities = [[NSMutableArray alloc] init];
You need to call some sort of initializer on NSMutableArray, don't you? initWithCapacity, or something like that? Not sure what you get if you leave it off.
** Just tested it. Make it [[NSMutableArray alloc] init] and you will be fine.
It was initialization problem for me.
Had to change from
NSMutableArray *myArray = [NSMutableArray mutableCopy]; // not initialized. don't know why this even compiles
[myArray addObject:someObject]; // crashed
to
NSMutableArray *myArray = [NSMutableArray new]; // initialized!