NSMutableArray EXC_BAD_ACCESS on contained objects
I have a class where I implement a NSMutableArray of objects. Now, when the phone goes into landscape mode, all of the objects in the NSMutableArray are deleted from the view (but not from the NSMutableArray), then when the phone goes back to portrait mode, I put all the objects contained in the NSMutableArray into the view, but when I try to access the first object I receive: EXC_BAD_ACCESS.
This is my code:
- (void) setObjects:(BOOL)hidden andWindow:(UIWindow *)win andTxt:(UITextView *)txt andTarget:(id) target {
//view
key = [win.subviews objectAtIndex:0];
key.hidden = hidden;
buttons = [[NSMutableArray alloc] initWithCapacity:1]; //my array
txtsms = txt;
[...]
}
- (void) addButton:(button *)but {
[key addSubview:[but returnButton]];
[buttons addObject:but];
[but release];
}
- (void) hiddenAllKey {
for (UIView *subview in [key subviews])
if ((subview.tag <= startSpecialPunctuation+1)&&(subview.tag >= spaceButton+1))
[subview removeFromSuperview];
}
- (void) showAllKey {
for(int i = 0; i < [buttons count]; ++i)
[key addSubview:[[buttons objectAtIndex:i] returnButton]]; //th开发者_StackOverflowis is the problem :|
}
As Joe Blow said, this is wrong:
- (void) addButton:(button *)but {
[key addSubview:[but returnButton]];
[buttons addObject:but];
[but release];
}
but
should not be released in that method. Similarly, this strikes fear in my heart:
- (void) setObjects:(BOOL)hidden andWindow:(UIWindow *)win andTxt:(UITextView *)txt andTarget:(id) target {
//view
key = [win.subviews objectAtIndex:0];
key.hidden = hidden;
buttons = [[NSMutableArray alloc] initWithCapacity:1]; //my array
Where do you release buttons
? Does your app only ever call that method once? If not, then you'll be leaking buttons
.
Try build and analyze
on your code, fixing any problems that it identifies. If it still crashes, post the backtrace of the crash
- (void) hiddenAllKey {
for (UIView *subview in [key subviews])
if ((subview.tag <= startSpecialPunctuation+1)&&(subview.tag >= spaceButton+1))
[subview removeFromSuperview];
}
This is subtly wrong too. You are removing elements from a list you are enumerating using fast enumeration. It can (should) fail easily.
Previously, I've written a category on UIView to do a remove all, that was doable with a simple while loop. Now, what you're trying to do... you might do a for loop where you manage the iterated index yourself, ie when you don't remove, you increment, else you keep it the same.
EDIT: suggestion of solution:
for (int idx = 0; idx < [[key subviews] count]; )
{
UIView *subview = [[key subviews] objectAtIndex: idx];
if ((subview.tag <= startSpecialPunctuation + 1) && (subview.tag >= spaceButton + 1))
{
[subview removeFromSuperview];
}
else
{
idx++;
}
}
精彩评论