【问题标题】:NSTextField Subclass Crashes on setLineBreakMode: methodNSTextField 子类在 setLineBreakMode 上崩溃:方法
【发布时间】:2015-12-29 05:16:33
【问题描述】:

我有一个 NSTextField 的子类,我设置了 LineBreakMode。

它在我的 Mac 和 Yosemite 下运行良好 我的一位用户在 Mavericks 上的崩溃

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[XTextField setLineBreakMode:]: unrecognized selector sent to instance 0x7fc784548ad0'

这一轮我该怎么做?

子类的头文件

#import <Cocoa/Cocoa.h>

@interface XTextField : NSTextField

- (void)setText:(NSString *)text

@end

实施

#import "XTextField.h"
@implementation XTextField

- (void)setText:(NSString *)text
{
    if (text)
    {
        [self setStringValue:text];
    }
    else
    {
        [self setStringValue:@""];
    }
 }


 - (instancetype)initWithFrame:(NSrect)frame
 {
     if(self = [super initWithFrame:frame])
     {
         [self setEditable:NO];
         [self setSelectable:NO];
         [self setDrawsBackGround:NO];
         [self setBezeled:NO];
     }
     return self;
 }
 @end

调用代码:

XTextField* myLabel = [[XTextField alloc]initWithFrame:myFrame];
[myLabel settext:@"text text text"];
[myLabel setLineBreakMode:NSLineBreakByTruncatingTail];

【问题讨论】:

  • 您是否检查了您的出口是否有文本字段...并发布了一些代码
  • @EICaptain 我没有网点,它是通过编程方式制作的 NSTextFieldSubClass
  • @EICaptain 我发布了崩溃的代码行还有什么代码要发布? NSTextFieldSubClass 是一个简单的子类,它只将方法 setStringValue 重命名为 setText
  • 您能否编辑您的问题以显示您如何声明“NSTextFieldSubClass”(例如 .h 文件的内容和/或“@interface”的外观)。此外,子类应该永远以“NS”开头,因为这可能会使其他人在查看您的代码时误以为它是 Apple 提供的 iOS SDK 类。
  • @MichaelDautermann 当然,请稍等。 (P.S. 它不是以“NS”开头的,我在这里重命名它是为了说明它是NSTextField的子类

标签: objective-c macos cocoa crash nstextfield


【解决方案1】:

这里有很多问题需要回答。如错误消息所示,问题在于 setLineBreakMode: 选择器被发送到无法识别该选择器的对象。会发生什么会导致这种情况?弄清楚这样的事情需要批判性思维和侦探工作。这里有一些想法。

  1. -setLineBreakMode: 似乎实际上并没有被NSTextField 实现;据我所知,这是NSCellNSMutableParagraphStyle 的一种方法。如果您有NSTextField(或其子类),您通常会调用[[myTextField cell] setLineBreakMode:...],但您的代码 sn-p 并不表示您正在这样做。所以除非你在你的子类中实现了这个方法——你没有声明你做了——这可能是崩溃的原因。也许您在 Mac 上看不到崩溃,因为无论出于何种原因,此代码路径都没有受到影响?或者也许苹果在优胜美地私下实现了这种方法,但在小牛队却没有?谁知道。您是否在该行收到编译器的警告,说该对象没有响应该选择器?不要忽略编译器警告。

  2. 您发布的代码看起来像是在类对象上调用setLineBreakMode:,而不是在类的实例上;通常类以大写字母开头,而实例以小写字母开头。遵守这样的编码约定可以让每个人都不会感到困惑。如果你的子类真的被命名为NSTextFieldSubClass,那么我同意@MichaelDautermann 的观点,你永远不应该用NS 前缀命名类;这既令人困惑又自找麻烦,因为据您所知,Apple 有一个与该名称完全相同的私有子类。以NS 开头的类名由Apple 保留。

  3. 这可能是您认为在您显然命名为 NSTextFieldSubClass 的变量中的对象根本不是您的子类的实例,或者已被释放(并且可能在相同的地址),或一些这样的问题,这就是它不响应选择器的原因。您可以通过打开NSZombieEnabled、在调试器中检查它、添加它的NSLog(可能在您的子类中添加-description 方法)或许多其他技术来调查此问题。

这一切都非常模糊,但问题是模糊的。您至少需要发布子类的代码、实例化子类的代码以及崩溃行周围的代码,以获得更具体的帮助。我们无法读懂你的想法,而且错误的根源很可能在这些地方之一。

【讨论】:

  • 我用实际代码更新了我的问题。看来您对cell 的看法是正确的,我会尝试的。
  • 我没有实现setLineBreakingMode 方法,但我想我会在我的子类中实现它(不是以NS 开头)这个方法,我猜它的实现应该只是[self.cell setLineBreakMode:mode];
  • 谢谢您的回答先生!
  • 混淆是因为:当我输入[myLabel setLine..]时,Xcode自动完成了它,所以我认为这是NSTextField的合法方法,但我查看了NSTextField的文档并且没有这样的方法-- 也没有显示警告
  • 嗯,奇怪。为什么在调用未声明的选择器时没有收到正确的警告以及正确的基于类型的选择器完成的问题可能是一个新的 stackoverflow 问题(如果该问题尚不存在)。正如这个问题所示,获得正确的警告/完成很重要。无论如何,祝你好运,很高兴目前的问题得到解决。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 2016-05-23
  • 1970-01-01
相关资源
最近更新 更多