Reputation: 33
I have a sqlite database with questions and I want to write a function to get N random questions from it. I use a for loop with n iterations. For each iteration I get a question with a random ID which is not repeated. I copy the element of each column in a variable of an object of the class "question". Until here, everything is perfect. I have used NSLog to print the questions through all the function and all the process is right until I try to add the last object to a NSMutablearray. All the positions are overwritten. This is my code:
-(NSMutableArray*)getNQuestions:(int)n
{
question *aQuestion=[[question alloc]init];
NSMutableArray *arrayOfChoosenQuestions=[[NSMutableArray alloc]initWithCapacity:n];
NSMutableIndexSet *choosenQuestionsIDs=[[NSMutableIndexSet alloc]init];
FMResultSet *rs;
int questionID;
for (int i=0; i<n; i++) {
questionID = (arc4random()%(NUMBER_OF_AVAILABLE_QUESTIONS-1))+1;
while ([choosenQuestionsIDs containsIndex:questionID]) {
questionID = (arc4random()%(NUMBER_OF_AVAILABLE_QUESTIONS-1))+1;
}
[choosenQuestionsIDs addIndex:questionID];
rs = [database executeQueryWithFormat:@"SELECT * FROM questions WHERE Questions.ID=%d", questionID];
if ([rs next] ) {
aQuestion.statement=[rs stringForColumn:@"Question"];
aQuestion.rightAnswer=[rs stringForColumn:@"Right_Answer"];
aQuestion.wrongAnswer1=[rs stringForColumn:@"Wrong_Answer_1"];
aQuestion.wrongAnswer2=[rs stringForColumn:@"Wrong_Answer_2"];
aQuestion.image=[rs stringForColumn:@"image"];
}
[arrayOfChoosenQuestions addObject:aQuestion];
}
return arrayOfChoosenQuestions;
}
This is an example of what happen
1rst iteration:
arrayOfChoosenQuestions=[question1]
2nd iteration
arrayOfChoosenQuestions=[question2 question2]
3rd iteration
arrayOfChoosenQuestions=[question3 question3 question3]
Thank You for your help
Upvotes: 1
Views: 386
Reputation: 243156
In addition to nhahtdh said, your method is overly complex. It could probably be simplified to this:
-(NSMutableArray*)fetchNQuestions:(int)n {
NSMutableArray *questions = [NSMutableArray array];
FMResultSet *rs = [database executeQueryWithFormat:@"SELECT * FROM questions ORDER BY RANDOM LIMIT %d", n];
while ([rs next]) {
Question *q = [[Question alloc] init];
[q setStatement:[rs stringForColumn:@"Question"]];
...
[questions addObject:q];
// if you're not using ARC:
[q release];
}
return questions;
}
Upvotes: 2
Reputation: 56819
You are re-using the same question
object (which is aQuestion
) over and over again, so you are actually modifying and inserting the same underlying object into the array.
Basically, in your current code, you are referring to the same block of memory when you are reading from/writing to aQuestion
. All modification will go to the same position in memory. As you can see, the change "propagate" to other objects, since they are actually the same memory block referred to by the pointer in aQuestion
.
For each loop, you have to create a new question
object to accommodate new data.
Upvotes: 3