Property '' not found on object of type 'id'

30,223

Solution 1

This code:

[anArray objectAtIndex:0].aVariable

Can be broken down into 2 sections:

[anArray objectAtIndex:0]

This returns an id- because you can put any type of object into an array. The compiler doesn't know what type is going to be returned by this method.

.aVariable

This is asking for the property aVariable on the object returned from the array - as stated above, the compiler has no idea what this object is - it certainly won't assume that it is an AnObject, just because that is what you added a line or two earlier. It has to evaluate each statement on its own. The compiler therefore gives you the error.

It is a little more forgiving when using accessor methods:

[[anArray objectAtIndex:0] aVariable];

This will give you a warning (that the object may not respond to the selector) but it will still let you run the code, and luckily enough your object does respond to that selector, so you don't get a crash. However this is not a safe thing to rely on. Compiler warnings are your friends.

If you want to use the dot notation, you need to tell the compiler what type of object is being returned from the array. This is called casting. You can either do this in two steps:

AnObject *returnedObject = [anArray objectAtIndex:0];
int value = returnedObject.aVariable;

Or with a mess of brackets:

int value = ((AnObject*)[anArray objectAtIndex:0]).aVariable;

The extra brackets are required to allow you to use dot notation when casting. If you want to use the accessor methods, you need fewer round brackets but more square brackets:

int value = [(AnObject*)[anArray objectAtIndex:0] aVariable];

Solution 2

-[NSArray objectAtIndex:] returns an id pointer. Since id does not contain information about your protocol the compiler cannot know the object has this property you declared; that is why it complains.

You can solve this by either cast the return value of objectAtIndex: or by using the getter/setter notation, i.e. [anArray objectAtIndex:0] setAVariable:...]. Also make sure you import your protocol definition, otherwise the compiler might also not know about the declared method and issue a warning.

Share:
30,223
user1070134
Author by

user1070134

Updated on July 09, 2022

Comments

  • user1070134
    user1070134 almost 2 years

    I'm getting Property 'aVariable' not found on object of type id when trying to read or write aVariable to the array. Shouldn't it be known what class the object is that I added? Also noticed that it works to read the value with NSLog(@" %@",[[anArray objectAtIndex:0] aVariable]);

    I'm a beginner at Objective C so it might be some simple thing I'm not getting.

    AnObject

    @interface AnObject : NSObject
    
    @property (nonatomic,readwrite) int aVariable;
    
    @end
    

    AnotherObject

    @interface AnotherObject : NSObject
    
    @end
    

    test.h

    #import "test.h"
    
    @implementation AnObject
    @synthesize aVariable;
    
    - (id)init
    {
        self = [super init];
        if (self) {
            aVariable=0;
        }
        return self;
    }  
    
    @end
    

    test.m

    @implementation AnotherObject
    
    - (id)init
    {
        self = [super init];
        if (self) { }
        return self;
    }  
    
    - (NSMutableArray*) addToArray
    {
        NSMutableArray* anArray = [[NSMutableArray alloc] initWithCapacity:0];
        AnObject* tempObject = [[AnObject alloc] init];
    
        tempObject.aVariable=10;
        [anArray addObject:tempObject];
    
        // Property 'aVariable' not found on object of type 'id'
        [anArray objectAtIndex:0].aVariable=[anArray objectAtIndex:0].aVariable + 1; 
    
        // Property 'aVariable' not found on object of type 'id'
        NSLog(@" %i",[anArray objectAtIndex:0].aVariable); 
    
        // This works
        NSLog(@" %i",[[anArray objectAtIndex:0] aVariable]); 
    
        return anArray;
    }
    
    @end
    
  • jscs
    jscs over 12 years
    For completeness, it should be noted that the dot syntax eventually uses the accessor method, too. The problem is that the compiler has no way to be sure what the accessor is for a property unless the object's type is known, because the accessor can have any name (@property (getter=numBananas) int numApples;, e.g.).
  • Old McStopher
    Old McStopher over 11 years
    +1 for noting the need for casting when using dot notation. (For my situation, where object types are determined at runtime, I just avoid the dot notation.)