Reputation: 327
My team and I are working on a quiz app and we have 1 view and we simply reload the text on the labels and buttons. Now when we start the quiz there are 2 loops which load the questions and answeres from a database. In those loops we initialize objects which are declared in the .h file. So what we do is: obj = [[class alloc] initwith:stuff]; It works perfectly until the 6th time we call the method where the 2 loops are. Sometimes it crashes in the first loop, sometimes in the second. Now the weird part is, that if we call the method twice on the "play again" button it will crash on the 3rd time already (method called 6 times then = crash), so we thought it has something to do with the memory or so. We tried to clean the project, ran it on an iPad and on the simulator. No effect. The errormessage is that the array we've filled in the first loop, is empty in the 2nd loop.
I can't give you a codesnipet at the moment, but the easiest way would be to simply reset the app when the user presses the "play again" button. Is there any easy way to do this? It would be also fine if the app would just close and reopen with the splashscreen.
If you can't make any suggestions right now, I'll add a codesnipet tomorrow
Thanks in advance
Edit: SIGABRT This is the error message: SoccerQuiz[1563:f803] * Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array' * First throw call stack: (0x159e022 0x172fcd6 0x158ad88 0x4719 0x3455 0x159fe99 0xe214e 0xe20e6 0x188ade 0x188fa7 0x188266 0x1073c0 0x1075e6 0xeddc4 0xe1634 0x1488ef5 0x1572195 0x14d6ff2 0x14d58da 0x14d4d84 0x14d4c9b 0x14877d8 0x148788a 0xdf626 0x20ed 0x2055) terminate called throwing an exception(lldb)
My code:
-(NSMutableArray*) readFromDatabase{
//if modus is true 20 questions will be loaded(untested). we set mds to 10 for now which works for the first 5 times and then crashes the 6th time
int mds = 0;
if (modus)
mds = 20;
else mds = 10;
bool loop = true;
//a_data is the array in which the data object is. it is filled with the questions and answeres
NSMutableArray * a_data = [[NSMutableArray alloc] init];
//check_id is the array in which the question ids from the database are saved
NSMutableArray * check_id = [[NSMutableArray alloc] init];
//ant is the array in which the 4 possible answers are saved.
NSMutableArray *ant = [[NSMutableArray alloc] init];
//in id_frage the id of the question is saved and in frage the question itself
NSString *id_frage = [[NSString alloc] init];
NSString *frage = [[NSString alloc] init];
//in sql_id the statement for the question is saved
NSString *sql_id = [[NSString alloc] initWithFormat:@"select id from QQUESTION where level = %@ order by random() limit 1", difficulty];
//in the method sqlquery we get data from the database
id_frage = [[self sqlquery: sql_id with:@"Q"] objectAtIndex:0];
[check_id addObject:id_frage];
NSLog(@"1");
//we use these loops to read unique question ids from the database, as you can see random questions are loaded from the database (sql_id statement)
for (int z = 0; z < mds; z++)
{
while (loop)
{
for (int y = 0; y <= check_id.count; y++)
{
//this loop checks if the question id is already in check_id
if ([[check_id objectAtIndex:y] isEqualToString:id_frage])
{
id_frage = [[self sqlquery: sql_id with:@"Q"] objectAtIndex:0];
break;
}
else {
//if the id doesnt already exit, it will be added to the check_id array
if (y == check_id.count-1)
{
[check_id addObject:id_frage];
loop = false;
break;
}
}
}
}
loop = true;
id_frage = [[self sqlquery: sql_id with:@"Q"] objectAtIndex:0];
}
NSLog(@"2");
//this loops loads the questions and answers that fit to the question ids
for (int x = 0; x < mds; x++)
{
//sql_q statement for the questions
NSString *sql_q = [[NSString alloc] initWithFormat:@"select TEXT from QQUESTIONTEXT where ID_QUESTION = '%@' and LANGUAGE = '%@'", [check_id objectAtIndex:x], language];
frage = [[self sqlquery:sql_q with:@"Q" ]objectAtIndex:0];
//sql_a statement for the answers
NSString *sql_a = [[NSString alloc] initWithFormat:@"select answer.correct, answertext.text from QANSWER as answer, QANSWERTEXT as answertext where answer.ID_QUESTION='%@' and answer.ID = answertext.ID_ANSWER and answertext.LANGUAGE = '%@'", [check_id objectAtIndex:x], language];
ant = [self sqlquery: sql_a with:@"A"];
//this loop sets the right answer at the first position of the array
for(int a = 0; a<ant.count-1; a++)
{
if([[ant objectAtIndex:a] isEqualToString:@"1"])
{
a++;
NSString *h = [[NSString alloc]initWithFormat:[ant objectAtIndex:1]];
[ant replaceObjectAtIndex:1 withObject:[ant objectAtIndex:a]];
[ant replaceObjectAtIndex:a withObject:h];
a--;
break;
}
}
//this data object 'd' is filled with a question and 4 answers and 10 or 20 will be added to a_data which will be returned
d = [[data alloc] initFrage:frage mitAntwort1:[ant objectAtIndex:1] Antwort2:[ant objectAtIndex:3] Antwort3:[ant objectAtIndex:5] Antwort4:[ant objectAtIndex:7]];
[a_data addObject:d];
}
NSLog(@"3");
return a_data;
}
Upvotes: 0
Views: 233
Reputation: 89192
There is no garbage collector on iOS -- there is either manual or automatic reference counting (ARC). In either case, objects are reference counted by using retain and release. With ARC, you don't have to make those calls yourself, but that doesn't mean you still can't run into problems.
Without your code or any information, I can only give general advice. I assume that your crash is EXC_BAD_ACCESS or some equivalent.
I wrote a blog to explain this problem and how to troubleshoot it
http://loufranco.com/blog/files/Understanding-EXC_BAD_ACCESS.html
In your case, this is what I would do
If that fails, then turn on the Debug Malloc and use the tools linked to in my blog to debug the problem.
EDIT BASED ON QUESTION EDIT:
You are getting an exception -- in the code you provided, there are several objectAtIndex calls -- create a breakpoint on exception using instructions here:
http://www.dosomethinghere.com/2011/04/18/xcode-4-exception-breakpoint/
And tell us the exact line.
Basically, you can't call objectAtIndex with 0 on an empty array -- so you need to check the length first.
Upvotes: 3
Reputation: 6976
In iOS there is no garbage collector feature.
Instead, there is ARC (Automatic Reference Counting)
Apple discusses ARC here: https://developer.apple.com/technologies/ios5/
ARC is compiler technology and uses retain counts to keep track of the objects
Thus, the most likely reason for app crash is accessing a released object.
This generally results in the compiler warning you of bad access!
In the header file, make sure to properly retain your objects with
@property(nonatomic,retain)Object* myobject;
Hope this helped!
Upvotes: 0