0

I have an NSMutableArray which returns me some object. The object which I added had properties name,age.

now when I use these properties on the Object returned (obj.name or obj.age ), Compiler says, no such member, use (->) instead of (.)

I understand that NSObject wont have these members and hence it wont understand the property.

But If i use setters, and getters as method ([obj name] or [obj age]) syntax instead of this properties, I dont get any errors.

But using property means calling a setter or getter only ?
ad Objective C is suppose to be dynamic language, right ?

Pooria Azimi
  • 8,585
  • 5
  • 30
  • 41
Amogh Talpallikar
  • 12,084
  • 13
  • 79
  • 135

2 Answers2

3

Do you cast the returned object to your object type (MyObject)?

You should do something like:

((MyObject*)[mutableArray objectAtIndex:0]).age = 20;

The reason you're not getting any errors when using [[mutableArray objectAtIndex:0] name] syntax is that you're calling a method on the returned object (which is of type id), and id s tend to not choke in the compile-time if you call a (yet) non-existant method on them. At the run-time, [mutableArray objectAtIndex:0] might resolve to type MyObject an in that case, the message [obj name] has a proper implementation (IMP). If it doesn't resolve to MyObject, your app will crash.

And note that the reason you're not even getting a compile-time warning is that Xcode knows that there is at least 1 class in your codebase that implements the method name, and it trusts you with calling this method only on instances of that class. if you do something like ((MyObject*)[mutableArray objectAtIndex:0]).ageeeeee = 20;, it'll give you a warning as there's a very good chance that it'll crash (no class in your app implements the method ageeeeee statically).

The type id does not have a property name, and that's why you can't use dot syntax.

Actually, this incident shows perfectly why ObjC is called a dynamic language!

Pooria Azimi
  • 8,585
  • 5
  • 30
  • 41
  • Thats fine. but the dot syntax is suppose to represent a call to setter or getter method. so shouldn't it work the way as a method call whether or not it existed ? anyways.. thanks for the clarification :) – Amogh Talpallikar Mar 09 '12 at 05:50
  • What if the property is supposed to be read only? Unless the compiler knows exactly which class/property you are talking about, it can't know whether you should be allowed to use it (at least in the case where you want to set the value). – UIAdam Mar 09 '12 at 05:55
  • @UIAdam: Nice point but if the property is readonly then, setter wont be generated, and i should get an "unrecognized selector sent to object exception" at runtime. – Amogh Talpallikar Mar 09 '12 at 06:00
  • @UIAdam: The compiler handles those cases properly. If you have only one other class `MyObject` with a `readonly` property of age, method calls such as `[[array objAtIndex:0] setAge:100];` will result in a warning too. If there are multiple classes with `age` properties and at least one of them is `readwrite`, then it won't produce any warnings. – Pooria Azimi Mar 09 '12 at 06:03
  • @AmoghTalpallikar It's rather complicated, but I think http://stackoverflow.com/a/1208421/347353 answers this question very well. – Pooria Azimi Mar 09 '12 at 06:04
1

That's right - dot syntax is not supported in such case.

You need to cast a pointer to the actual class:

((MyObject*)[array objectAtIndex: 0]).name = @"Bill";
sigman
  • 1,291
  • 12
  • 13