Can I replace NSMatrix contents in the action method
Can I replace NSMatrix contents in the action method
- Subject: Can I replace NSMatrix contents in the action method
- From: Jeffrey Scofield <email@hidden>
- Date: Wed, 24 Dec 2008 16:46:36 -0800
I have an application that was crashing mysteriously. After much
effort I boiled it down to a fairly small example, reproduced
below.
In the example, there's an NSMatrix containing 9 NSButtonCells.
When the user clicks on one of the buttons, all of the button
cells are replaced with newly allocated ones. In fact, they're
replaced twice. The first time is with direct instances of
NSCell (representing inactive areas of the matrix), then with new
NSButtonCells. (Keep in mind that this is boiled down from a
larger application.)
What I find is that this pattern causes memory corruption and
then a crash, even though I seem to be following all the rules
for what to retain and release. I can certainly fix the problem
in various ways, but what I want to know is whether this type of
coding is supposed to be allowed. If so, there might be a bug in
Cocoa. If not, I'm wondering how I can avoid making similar
mistakes in the future. I'd especially appreciate pointers to
documentation that would help me avoid them.
Regards,
Jeff Scofield
Seattle
----- 8< ------------ example code follows ------------- >8 -----
// This example has an associated Nibfile containing two objects of
// interest: an instance of NewCell and an instance of NSMatrix.
// The matrix action is set up to send the "clicked" selector to
// the instance of NewCell. The "matrix" outlet of the NewCell
// is set to the matrix.
// What you should see when you run it is a 3 x 3 array of buttons,
// each labelled with the number of times it has been clicked. It
// works, but every now and then it crashes horribly.
#import <Cocoa/Cocoa.h>
@interface NewCell : NSObject
{
NSMatrix *theMatrix;
int theCounts[3][3];
}
- (NSMatrix *) matrix;
- (void) setMatrix: (NSMatrix *) newMatrix;
- (void) clicked: (id) sender;
@end
@implementation NewCell
- (NSMatrix *) matrix
{
return theMatrix;
}
- (void) setMatrix: (NSMatrix *) newMatrix
{
theMatrix = newMatrix;
}
NSImage *label(int count)
{
NSFont *font = [NSFont fontWithName: @"Times Roman" size: 22.0];
NSString *scount = [NSString stringWithFormat: @" %d", count];
NSRange fullrange = NSMakeRange(0, [scount length]);
NSMutableAttributedString *s =
[[NSMutableAttributedString alloc] initWithString: scount];
[s addAttribute: NSFontAttributeName value: font range: fullrange];
NSImage *img = [[NSImage alloc] initWithSize: NSMakeSize(162.0,
43.0)];
[img setCachedSeparately: YES];
[img lockFocus];
[s drawInRect: NSMakeRect(0.0, 0.0, 162.0, 43.0)];
[img unlockFocus];
[s release];
return img;
}
void redisplay(int counts[3][3], id sender)
{
int i, j;
NSImage *img;
NSButtonCell *bcell;
for(i = 0; i < 3; i++)
for(j = 0; j < 3; j++) {
NSCell *cell = [[NSCell alloc] init];
[sender putCell: cell atRow: i column: j];
[cell release];
}
for(i = 0; i < 3; i++)
for(j = 0; j < 3; j++) {
bcell = [[NSButtonCell alloc] init];
img = label(counts[i][j]);
[bcell setImage: img];
[sender putCell: bcell atRow: i column: j];
[img release];
[bcell release];
}
}
- (void) clicked: (id) sender
{
int row = [sender selectedRow];
int col = [sender selectedColumn];
if(row < 3 && col < 3)
theCounts[row][col]++;
redisplay(theCounts, sender);
}
- (void) awakeFromNib
{
[theMatrix renewRows: 3 columns: 3];
[theMatrix setCellSize: NSMakeSize(162.0, 43.0)];
[theMatrix sizeToCells];
redisplay(theCounts, theMatrix);
}
@end
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden