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

时间:2011-11-15 05:53:02

标签: objective-c

我正在学习使用iOS 5中的新故事板功能获取基本列表视图 - >详细视图基于导航的应用程序。为了消除复杂性,我只是在数组中模拟我的数据。该数组是一个自定义类(“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;

在主要的VehicleModel上:

@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)   终止调用抛出异常当前语言:auto;目前的目标-c

2 个答案:

答案 0 :(得分:1)

assign类型的对象(与标量相对)属性是不常见的。我希望将其视为retaincopy

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

答案 1 :(得分:1)

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