简体   繁体   中英

Difference between [object variable] and object.variable in Obj-C?

I was working on a program today and hit this strange bug. I had a UIButton with an action assigned. The action was something like:

-(void) someaction:(id) e
{
    if ([e tag]==SOMETAG)
    {
        //dostuff
    }
}

What confuses me is that when I first wrote it, the if line was

if (e.tag==SOMETAG)

XCode refused to compile it, saying

error: request for member 'tag' in 'e', which is of non-class type 'objc_object*'

but I thought the two were equivalent.

So under what circumstances are they not the same?

Using the dot notation is only possible if the variable has an associated property declared, or if there are Key-Value-Coding compliant accessor methods available. The property syntax allows you to 'synthesise' accessor methods for your variable that are Key-Value-Coding compliant, and really, this is how the dot notation works.

When a property is declared, someObject.variable is equivalent to [someObject variable] .

When an object is typed as id, the compiler isn't aware of any properties the object has. id is a pointer to any object, effectively a void*.

You could cast your object to the type that you expect it to be, which would allow you to then use the property syntax.

((MyObject*)e).tag

There seems to be some misconception about properties and dot notation going on here. Dot notation can be used with any accessor method whether declared as a property or not, provided that the compiler knows that the object to the left of the dot has the accessor. You do not need to use the @property syntax. You do not need to synthesize the accessor. The following is perfectly valid Objective-C which will compile cleanly:

#import <Cocoa/Cocoa.h>
@interface AClass
{
}

-(NSString*) aProperty;

@end

@implementation AClass

-(NSString*) aProperty
{
    return @"some text";
}

@end

int main()
{
    AClass* foo = [[ACLass alloc] init];
    NSLog(@"%@", foo.aProperty);
    return 0;
}

The critical point is that the compiler has to know if the accessor exists for the object which means that the object must be correctly typed (ie can't be id).

You can use the obj.prop getter syntax provided (handwavily) that the compiler has a prototype for the method call [obj prop], and the setter syntax provided there's [obj setProp:blah]. This means you can use it with classes like NSNumberFormatter which don't declare properties. Whether this is advisable or not is up for debate.

You can cast it to the right object type with ((Foo*)obj).prop, if you don't mind all the parentheses.

Note that the return type of an unknown method defaults to id (so you might be comparing an id to an int), and also that your sender might not be a UIView (it could be a UIBarButtonItem). It's a bit safer to do if ([(id<NSObject>)e isKindOfClass:[UIView class]] && [(UIView*)e tag] == sometag) , if you assume that e conforms to <NSObject>.

You can't use dot notation on id objects. It's just a rule they have.

This is for Jack who deleted his answer before I could comment :-)

You're not accessing the instance variable directly, the dot notation is only used for getting at properties, via the getter and setter methods that you @synthesized. You're sending a message to the object, which in this case causes those getter/setter methods to get called. You can't use the dot notation to access a member variable directly, or call a method directly - it has to be set up as a property.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM