Свойство '' не найдено для объекта типа 'id' - PullRequest
19 голосов
/ 29 ноября 2011

Я получаю Property 'aVariable' not found on object of type id при попытке прочитать или записать переменную в массив.Разве не должно быть известно, к какому классу относится объект, который я добавил?Также заметил, что он работает для чтения значения с NSLog(@" %@",[[anArray objectAtIndex:0] aVariable]);

Я новичок в Objective C, так что это может быть какая-то простая вещь, которую я не получаю.

@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

Ответы [ 2 ]

38 голосов
/ 29 ноября 2011

Этот код:

[anArray objectAtIndex:0].aVariable

Можно разбить на 2 раздела:

[anArray objectAtIndex:0]

Это возвращает id - потому что вы можете поместить любой тип объекта в массив. Компилятор не знает, какой тип будет возвращен этим методом.

.aVariable

Это запрашивает свойство aVariable для объекта, возвращаемого из массива - как указано выше, компилятор не знает, что это за объект - он, конечно, не будет предполагать, что это AnObject, просто потому, что это то, что вы добавили одну или две строки ранее. Он должен оценивать каждое утверждение самостоятельно. Поэтому компилятор выдает ошибку.

Это немного более простительно при использовании методов доступа:

[[anArray objectAtIndex:0] aVariable];

Это даст вам предупреждение (что объект может не реагировать на селектор), но все равно позволит вам запустить код, и, к счастью, ваш объект отвечает на этот селектор, так что вы не не терпит крах Однако на это нельзя полагаться. Предупреждения компилятора - ваши друзья.

Если вы хотите использовать точечную нотацию, вам нужно сообщить компилятору, какой тип объекта возвращается из массива. Это называется casting . Вы можете сделать это в два этапа:

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

Или с кучей скобок:

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

Дополнительные скобки необходимы, чтобы вы могли использовать точечную нотацию при приведении. Если вы хотите использовать методы доступа, вам нужно меньше круглых скобок, но больше квадратных скобок:

int value = [(AnObject*)[anArray objectAtIndex:0] aVariable];
1 голос
/ 29 ноября 2011

-[NSArray objectAtIndex:] возвращает указатель id. Поскольку id не содержит информации о вашем протоколе, компилятор не может знать, что объект обладает объявленным вами свойством; вот почему он жалуется.

Вы можете решить это, приведя возвращаемое значение objectAtIndex: или используя нотацию получателя / установщика, т.е. [anArray objectAtIndex:0] setAVariable:...]. Также убедитесь, что вы импортируете определение протокола, иначе компилятор может не знать об объявленном методе и выдаст предупреждение.

...