Свойство '' не найдено на объекте типа 'id'
Я получаю Property 'aVariable' not found on object of type id
при попытке чтения или записи aVariable в массив. Разве не должно быть известно, какой класс является объектом, который я добавил? Также заметил, что он работает, чтобы прочитать значение с помощью NSLog(@" %@",[[anArray objectAtIndex:0] aVariable]);
Я новичок в Objective C, поэтому это может быть какая-то простая вещь, которую я не получаю.
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
Ответы
Ответ 1
Этот код:
[anArray objectAtIndex:0].aVariable
Можно разбить на 2 раздела:
[anArray objectAtIndex:0]
Это возвращает id
- потому что вы можете поместить любой тип объекта в массив. Компилятор не знает, какой тип будет возвращен этим методом.
.aVariable
Это запрашивает свойство aVariable
объекта, возвращенного из массива - как указано выше, компилятор понятия не имеет, что это за объект - он, конечно же, не будет считать, что это AnObject
, просто потому, что это то, что вы добавили строку или две раньше. Он должен оценивать каждое утверждение самостоятельно. Поэтому компилятор дает вам ошибку.
Это немного легче простить при использовании методов доступа:
[[anArray objectAtIndex:0] aVariable];
Это даст вам предупреждение (что объект может не отвечать на селектор), но он все равно позволит вам запустить код, и, к счастью, ваш объект отвечает на этот селектор, так что вы не получите сбой. Однако это небезопасно, на что можно положиться. Предупреждения компилятора - ваши друзья.
Если вы хотите использовать точечную нотацию, вам нужно сообщить компилятору, какой тип объекта возвращается из массива. Это называется литье. Вы можете сделать это в два этапа:
AnObject *returnedObject = [anArray objectAtIndex:0];
int value = returnedObject.aVariable;
Или с беспорядком скобок:
int value = ((AnObject*)[anArray objectAtIndex:0]).aVariable;
Дополнительные скобки необходимы, чтобы вы могли использовать точечную нотацию при кастинге. Если вы хотите использовать методы доступа, вам нужно меньше круглых скобок, но больше квадратных скобок:
int value = [(AnObject*)[anArray objectAtIndex:0] aVariable];
Ответ 2
-[NSArray objectAtIndex:]
возвращает указатель id
. Поскольку id
не содержит информации о вашем протоколе, компилятор не может знать, что у объекта есть это свойство, которое вы объявили; поэтому он жалуется.
Вы можете решить это, либо произведя возвращаемое значение objectAtIndex: либо используя нотацию getter/setter, т.е. [anArray objectAtIndex:0] setAVariable:...]
. Также убедитесь, что вы импортируете определение протокола, иначе компилятор также не может знать об объявленном методе и выдавать предупреждение.