奇怪的“无法识别的选择器”问题

Posted

技术标签:

【中文标题】奇怪的“无法识别的选择器”问题【英文标题】:Strange "Unrecognized Selector" Issue 【发布时间】:2011-11-15 05:53:01 【问题描述】:

我正在学习将 ios 5 中的新 Storyboards 功能用于基本列表视图 -> 基于导航的详细视图应用程序。为了消除复杂性,我只是在一个数组中模拟我的数据。该数组是一个自定义类(“VehicleModel”),具有多个属性和一个初始化程序。

大多数属性只是 NSStrings,但有一个是指向“VehicleEngineInfo”对象的指针,该对象有一个属性(“engineType”)和一个初始化器:

-(id)initWithType:(NSString*)type 
  if(self = [super init]) 
    [self setEngineType: type];
  
  return self;

我有一个更具体的 VehicleEngineElectric 类,它扩展了 VehicleEngineInfo 并添加了一个属性(“cellCountMask”)并有自己的初始化程序:

-(id)initWithCellCountMask:(Byte)mask 
  if(self = [super initWithType:ENGINETYPE_ELECTRIC]) 
    [self setCellCountMask:mask];
  
  return self;

当我为数据数组创建“VehicleModel”的新实例时,我这样调用初始化程序:

VehicleModel *m1 = [[VehicleModel alloc] initWithName:@"name" Brand:@"brand" Model:@"model" Type:TYPE_CAR Status:STATUS_ACTIVE EngineInfo:[[VehicleEngineElectric alloc] initWithCellCountMask:0x01] Image:IMAGE_CAR];

如果我立即尝试读回 engineType 属性 ([[m1 engineInfo]engineType]),它可以正常工作。当我尝试以不同的方法(例如 prepareForSegue :) 读取相同的 engineType 属性时,我得到一个 NSInvalidArgumentException 并带有可爱的“无法识别的选择器发送到实例......”消息。我可以很好地读回 VehicleInfo 对象上的任何其他属性 - 只有 VehicleEngineInfo 属性会导致问题。

我的第一个想法是这是一个内存管理问题(保留/释放),但我启用了 ARC,所以不应该这样。当我离开创建它的方法时,为什么 engineType 属性会丢失?

更新: @property 声明如下所示...

关于 VehicleEngineInfo:

@property (nonatomic, assign) NSString* engineType;

在 VehicleEngineElectric 上:

@property (nonatomic, assign) Byte cellCountMask;

在主车辆模型上:

@property (nonatomic, assign) VehicleEngineInfo* engineInfo;
@property (nonatomic, assign) NSString* name;
@property (nonatomic, assign) NSString* brand;
@property (nonatomic, assign) NSString* model;
@property (nonatomic, assign) NSString* type;
@property (nonatomic, assign) NSString* status;
@property (nonatomic, assign) VehicleEngineInfo* engineInfo;
@property (nonatomic, assign) UIImage* image;

@synthesize 语句只有属性的名称,所以它们没有什么特别之处。

错误信息是这样的:

2011-11-14 23:33:42.951 TableTest[15640:fb03] -[__NSArrayI engineType]:无法识别的选择器发送到实例 0x6a89d90 2011-11-14 23:33:42.953 TableTest[15640:fb03] * 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[__NSArrayI engineType]:无法识别的选择器发送到实例 0x6a89d90” * 首先抛出调用栈: (0x129b052 0x174cd0a 0x129cced 0x1201f00 0x1201ce2 0x35ff 0x705e1e 0x3716d9 0x371952 0xbf986d 0x126f966 0x126f407 0x11d27c0 0x11d1db4 0x11d1ccb 0x1f53879 0x1f5393e 0x2e1a9b 0x24b8 0x2415) 终止调用抛出异常当前语言:自动;目前客观-c

【问题讨论】:

我们能否看到 engineInfo 和 engineType 的 @property 声明和 @synthesize 声明? 您没有向我们展示足够的代码来诊断问题。向我们展示属性声明和完整的错误消息,这将告诉我们哪些选择器未被识别。 【参考方案1】:

拥有assign 类型的对象(相对于标量)属性是不常见的。我希望将它们视为retaincopy

看起来你的engineInfo 属性正在被释放并且内存被重新分配给某处的NSArray,然后你正在询问对象并得到无法识别的选择器错误,因为你的指针现在指向一个完全不同的对象。

【讨论】:

将其设置为保留解决了该问题。非常感谢!【参考方案2】:

一般来说, 对象使用类型:保留 NSString 使用的类型:copy 其他像 int、float 等(甚至是委托)使用 assign 尝试@jrturton 的建议,但不确定这是否是导致您的问题的真正原因。

【讨论】:

感谢您提供使用什么和何时使用的参考。我需要复习一下这些到底是什么意思。

以上是关于奇怪的“无法识别的选择器”问题的主要内容,如果未能解决你的问题,请参考以下文章

Swift 3:将无法识别的选择器发送到手势识别器实例

目标动作模式的快速无法识别的选择器

无法识别的选择器 NSInvalidArgumentException:对于 IBAction?

NSInvalidArgumentException,使用 performSegueWithIdentifier 时发送到实例的无法识别的选择器

在访问 PFObject 成员时解析“发送到实例的无法识别的选择器”

快速代码崩溃:“发送到实例的无法识别的选择器”