【发布时间】:2012-07-28 23:33:42
【问题描述】:
在我的应用程序中有一个NSWindowController 的子类。在- (void)awakeFromNib 中,我创建了一个NSView 子类的实例来创建底部放置的按钮栏:
self.buttonBar = [[CNButtonBar alloc] initWithSize:NSMakeSize(tableViewRect.size.width-1, 25)];
CNButtonBar 这个东西有一个方法可以给自己添加按钮。我创建了两个:
[buttonBar addButtonWithTitle:nil
image:[NSImage imageNamed:NSImageNameAddTemplate]
target:self
action:@selector(btnAccountAddAction:)
alignment:CNBarButtonAlignLeft];
[buttonBar addButtonWithTitle:nil
image:[NSImage imageNamed:NSImageNameRemoveTemplate]
target:self
action:@selector(btnAccountRemoveAction:)
alignment:CNBarButtonAlignLeft];
这两个操作方法在NSViewController 的同一个实例中定义,我在其中发送两个addButtonWithTitle:... 消息。
用于设置动作的方法定义如下:
- (void)btnAccountAddAction:(id)sender
{
....
}
- (void)btnAccountRemoveAction:(id)sender
{
....
}
但是,它不起作用。每次如果我单击这两个按钮之一,我的应用程序就会崩溃并抛出如下异常:
-[__NSArrayM btnAccountAddAction:]: unrecognized selector sent to instance 0x1001454e0
检查过这个异常是绝对正确的。 NSArray 没有我想调用的这种方法。但是,有时抛出此异常的对象会发生变化。有时有__NSData 对象,有时有__NSDictionary 等等。似乎接收者不是我的NSWindowController 子类。但是给定的实例 ID 0x1001454e0 与我的 NSWindowController 相同。
这让我想把头发扯下来!这里出了什么问题……? 谢谢。
更新
我不得不说,CNButtonBar 和CNButtonBarButton 都是完全由代码绘制的。 addButtonWithTitle:image:target:action:alignment:的完整方法在这里(记住,这发生在CNButtonBar,NSView的子类(我应该用NSViewController代替它吗?),CNButtonBarButton是NSButton的子类):
- (void)addButtonWithTitle:(NSString*)title image:(NSImage*)image target:(id)target action:(SEL)action alignment:(CNBarButtonAlign)align
{
if (self.buttons == nil)
self.buttons = [[NSMutableArray alloc] init];
CNButtonBarButton *button = [[CNButtonBarButton alloc] init];
[self.buttons addObject:button];
button.title = title;
button.image = image;
button.target = target;
button.action = action;
button.align = align;
NSRect buttonRect;
NSSize titleSize = NSMakeSize(0, 0);
if (button.title.length > 0) {
NSMutableParagraphStyle* textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
[textStyle setAlignment: NSCenterTextAlignment];
NSColor *textColor = [[NSColor blackColor] colorWithAlphaComponent:0.9];
NSShadow* textShadow = [[NSShadow alloc] init];
[textShadow setShadowColor: [NSColor whiteColor]];
[textShadow setShadowOffset: NSMakeSize(0, -1)];
[textShadow setShadowBlurRadius: 0];
button.titleTextAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSFont fontWithName:@"Helvetica Neue" size:11.0], NSFontAttributeName,
textShadow, NSShadowAttributeName,
textColor, NSForegroundColorAttributeName,
textStyle, NSParagraphStyleAttributeName,
nil];
titleSize = [title sizeWithAttributes:button.titleTextAttributes];
buttonRect = NSMakeRect(0, 0, roundf(titleSize.width) + kTextInset * 2, NSHeight(self.frame) - 1);
}
if (button.image != nil) {
NSSize imageSize = [image size];
if (button.title.length == 0) {
buttonRect = NSMakeRect(0, 0, imageSize.width + kImageInset * 2, NSHeight(self.frame) - 1);
} else {
buttonRect = NSMakeRect(0, 0,
(imageSize.width + kImageInset * 2) + (roundf(titleSize.width) + kTextInset),
NSHeight(self.frame) - 1);
}
}
switch (self.align) {
case CNButtonBarAlignNormal: {
switch (button.align) {
case CNButtonBarButtonAlignLeft: {
button.frame = NSMakeRect(offsetLeft, 0, NSWidth(buttonRect), NSHeight(buttonRect));
offsetLeft += 1 * [self.buttons indexOfObject:button] + NSWidth(button.frame);
break;
}
case CNButtonBarButtonAlignRight: {
button.frame = NSMakeRect(offsetRight - NSWidth(buttonRect), 0, NSWidth(buttonRect), NSHeight(buttonRect));
offsetRight -= 1 * [self.buttons indexOfObject:button] + NSWidth(button.frame);
break;
}
}
break;
}
case CNButtonBarAlignCentered: {
break;
}
}
[self addSubview:button];
}
更新 2
问题解决了。经过一些调试,我发现这一定是 ARC 自动保留/释放的问题。我是对的。但问题是我的NSViewController 子类。由于将实例作为局部变量(没有强指针)而泄漏。感谢Sean D.,它为我指明了正确的方向。 (-;
【问题讨论】:
-
您可能应该显示以下代码:btnAccountAddAction
-
问题很可能出在
CNButtonBar,但如果没有来自addButtonWithTitle:的一些代码或信息,我们将无法诊断。 -
“我创建了一个 NSView 子类的实例来创建一个底部放置的按钮栏”——这听起来像是一些 other 类,而不是窗口控制器,正在创建 CNButtonBar实例。如果是这种情况,则其他类将自己设置为目标,但选择器方法由 win ctrllr 持有。这将解释“无法识别的选择器”异常 - 但不是被调用类的奇怪分类。
-
@HannesSverrisson 这些方法实际上是空的。只有一条日志消息。我给你一个更新。
标签: objective-c action target nsbutton nswindowcontroller