开发者

Xcode refuses to compile when trying to get property from custom object out of array

I've been running into this problem a lot lately. I have an NSMutableArray called tests which is populated with instances of my custom class Test. I'm trying to access a property with the following method:

return [tests objectAtIndex:row].name;

However LLVM always throws an error and refuses to compile:

error: Semantic Issue: No member named 'name' in 'struct objc_object'

How do I tell the compiler that I'll be accessing a Test object and to l开发者_运维百科et me compile the damned thing?


In order to use the dot notation for properties, the compiler needs to know the object's type.

You can send a message:

return [[test objectAtIndex:row] name];

Or you can cast the value returned by objectAtIndex::

return ((Test*)[tests objectAtIndex:row]).name;

You might wonder why. The compiler needs to know the object's type because a property can designate any method to be the getter or the setter, not just the default pair of name and setName:, for example, this is usual with BOOL properties:

@property(getter=isEditable) BOOL editable;

So the compiler needs to know what property this is in order to generate the correct accessor calls.


Since objectAtIndex: returns id, that is, a generic pointer, the compiler can't possibly know what method name to substitute for your property access .name.

You have to completely specify to the compiler what you want to do in this case. Either specify the exact method name:

[[tests objectAtIndex:row] name];

or specify the actual type of the object:

((Test *)[tests objectAtIndex:row]).name;

When you write foo.bar, the compiler has to look in foo's class and find the method names associated with the property bar. Those are usually bar/setBar:, but they could be anything;* because of that ambiguity, the compiler needs to know the actual class of foo. Given only a generic pointer, it can't find that information.

The warning indicates that the compiler also checked whether the object on the left side of the . is a struct with a field called name. There isn't such a field, so the compiler does not know what you want it to do.


*E.g., @property(retain, setter=putThisValueIntoBar, getter=hamAndEggs) Bar * bar;


Adding an explicit cast should do the trick.

Test *test = [tests objectAtIndex:row];
test.name

Or send a message instead of calling a method.

[[tests objectAtIndex:row] name]


Or you can caste it like this:

return ((Test*)[tests objectAtIndex:row]).name;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜