user253667
user253667

Reputation:

Strange "Unrecognized Selector" Issue

I am learning to use the new Storyboards feature in iOS 5 for a basic list view -> detail view nav-based app. To eliminate complexity, I am just mocking up my data in an array. The array is of a custom class ("VehicleModel") with several properties and an initializer.

Most of the properties are just NSStrings, but one is a pointer to an "VehicleEngineInfo" object, which has a single property ("engineType") and an initializer:

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

I have a more specific VehicleEngineElectric class that extends VehicleEngineInfo and adds a property ("cellCountMask") and has its own initializer:

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

When I create a new instance of "VehicleModel" for the data array, I call the initializer like this:

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

If i immediately try to read back the engineType property ([[m1 engineInfo]engineType]), it works fine. When I try to read the same engineType property in a different method (such as prepareForSegue:), I get an NSInvalidArgumentException with the lovely "unrecognized selector sent to instance..." message. I can read back any of the other properties on the VehicleInfo object just fine - only the VehicleEngineInfo property causes a problem.

My first though was that this was a memory management problem (retain/release) but I have ARC enabled so that shouldn't be it. Why does the engineType property get lost when I leave the method in which it was created?

UPDATE: The @property declarations look like this...

On VehicleEngineInfo:

@property (nonatomic, assign) NSString* engineType;

On VehicleEngineElectric:

@property (nonatomic, assign) Byte cellCountMask;

On the main 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;

The @synthesize statements just have the names of the properties, so theres nothing special about them.

The error message is this:

2011-11-14 23:33:42.951 TableTest[15640:fb03] -[__NSArrayI engineType]: unrecognized selector sent to instance 0x6a89d90 2011-11-14 23:33:42.953 TableTest[15640:fb03] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI engineType]: unrecognized selector sent to instance 0x6a89d90' * First throw call stack: (0x129b052 0x174cd0a 0x129cced 0x1201f00 0x1201ce2 0x35ff 0x705e1e 0x3716d9 0x371952 0xbf986d 0x126f966 0x126f407 0x11d27c0 0x11d1db4 0x11d1ccb 0x1f53879 0x1f5393e 0x2e1a9b 0x24b8 0x2415) terminate called throwing an exceptionCurrent language: auto; currently objective-c

Upvotes: 0

Views: 368

Answers (2)

Kjuly
Kjuly

Reputation: 35131

Generally speaking,
Types of Object use: retain
Type of NSString uses: copy
Others like int, float, etc(and even the delegate) use assign
Try @jrturton's suggestion, but not sure if it is the really reason that causes your problem.

Upvotes: 1

jrturton
jrturton

Reputation: 119242

It is unusual to have object (as opposed to scalar) properties of the assign type. I would expect to see them as retain or copy.

What it looks like is that your engineInfo property is getting released and the memory is re-assigned to an NSArray somewhere, you are then interrogating the object and getting the unrecognized selector error since your pointer is now pointing at a totally different object.

Upvotes: 1

Related Questions