I create an array of objects. These objects have a public variable correct
. When I have xcode optimization turned off everything in my project works great, but when I have any sort of optimization set then things go awry. The very first time I create one of these objects the correct
variable always returns false when accessed from another class. But subsequent creation of this class object returns the correct value for correct
. Here is a snippit of my code and the problem.
.h
@interface ShellQuestionAnswer : UIView
{
...
@public
bool correct;
...
}
.m
-(void)setLetter:(NSString*)letter forAnswer:(XMLNode*)answer withResponse:(XMLNode*)response
{
...
correct = [[[answer attributes] valueForKey:@"Correct"] isEqualToString:@"true"];
//Putting NSLog here shows "correct" to be true
}
And the class that uses this object:
-(void)addQuestion:(XMLNode*) rootNode ID:(NSString*)ID
{
...
answer1 = [[ShellQuestionAnswer alloc] initWithFrame:CGRectMake(0, currentY, textContainer.frame.size.width, 50)];
[answer1 setLetter:@"A" forAnswer:[answerstextArray objectAtIndex:0] withResponse:[responsestextArray objectAtIndex:0]];
currentY += answer1.frame.size.height + QUESTION_SEPARATION;
if(!answerObjects)
{
answerObjects = [[NSMutableArray alloc] init];
}
else
{
[answerObjects removeAllObjects];
}
[answerObjects addObject:answer1];
answer2 = [[ShellQuestionAnswer alloc] initWithFrame:CGRectMake(0, currentY, textContainer.frame.size.width, 50)];
[answer2 setLetter:@"B" forAnswer:[answerstextArray objectAtIndex:1] withResponse:[responsestextArray objectAtIndex:1]];
currentY += answer2.frame.size.height + QUESTION_SEPARATION;
[answerObjects addObject:answer2];
[textContainer addSubview:answer1];
[answer1 setUserInteractionEnabled:YES];
[textContainer addSubview:answer2];
[answer2 setUserInteractionEnabled:YES];
if([answerstextArray count] > 2)
{
answer3 = [[ShellQuestionAnswer alloc] initWithFrame:CGRectMake(0, currentY, textContainer.frame.size.width,50)];
[answer3 setLetter:@"C" forAnswer:[answerstextArray objectAtIndex:2] withResponse:[responsestextArray objectAtIndex:2]];
[textContainer addSubview:answer3];
currentY += answer3.frame.size.height + QUESTION_SEPARATION;
[answerObjects addObject:answer3];
[answer3 setUserInteractionEnabled:YES];
}
if([answerstextArray count] > 3)
{
answer4 = [[ShellQuestionAnswer alloc] initWithFrame:CGRectMake(0, currentY, textContainer.frame.size.width, 50)];
[answer4 setLetter:@"D" forAnswer:[answerstextArray objectAtIndex:3] withResponse:[responsestextArray objectAtIndex:3]];
[textContainer addSubview:answer4];
currentY += answer4.frame.size.height + QUESTION_SEPARATION;
[answerObjects addObject:answer4];
[answer4 setUserInteractionEnabled:YES];
}
[textContainer setNeedsDisplay];
for(ShellQuestionAnswer *answer in answerObjects)
{
if(answer->correct) //<-- always returns false the first time I run this function
{
if(!self.correctAnswer)
{
self.correctAnswer = [[NSMutableArray alloc] init];
}
[self.correctAnswer addObject:answer];
}
}
}
I have logged everything and don't understand why the answer->correct
returns false when outside the object, but inside the answer
object the variable correct
is actually true. And this only happens when optimization is on (any mode) and only on the first instance of this class being used.
If I change the correct
variable into a property instead of a public class member variable then the issue is no longer present. I'm fine with this solution, but I am not fine with not understanding why this happens. This issue could be present in any of the other classes in my code and I do not know where until a customer complains of a random quirk the first time it runs. That is unacceptable to me. Anyone have any ideas on why optimization messes up my code?
EDIT: To be clearer, here are the test cases I am using. One works, one does not (in the fashion mentioned above).
Working:
@interface ShellQuestionAnswer : UIView
{
...
@public
//bool correct;
...
}
@property (nonatomic, assign) bool correct;
Not working:
@interface ShellQuestionAnswer : UIView
{
...
@public
bool correct;
...
}
Those are the only lines changed to get a working set (apart from answer->correct
changing to answer.correct
inside the for loop for the property case).