Obj-C中[object variable]和object.variable之间的区别?

时间:2010-06-10 23:42:43

标签: iphone objective-c cocoa xcode

我今天正在制作一个程序并且遇到了这个奇怪的错误。我有一个分配了动作的UIButton。行动就像:

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

令我困惑的是,当我第一次写它时, if 行是

if (e.tag==SOMETAG)

XCode拒绝编译它,说

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

但我认为两者是等价的。

那么在什么情况下他们不一样?

5 个答案:

答案 0 :(得分:5)

仅当变量具有声明的关联属性,或者存在可用的符合键值编码的访问器方法时,才可以使用点表示法。属性语法允许您为符合键值编码的变量“合成”访问器方法,实际上,这就是点符号的工作方式。

声明属性时,someObject.variable相当于[someObject variable]

当对象键入为id时,编译器不知道该对象具有的任何属性。 id是指向任何对象的指针,实际上是void *。

您可以将对象转换为您期望的类型,这样您就可以使用属性语法。

((MyObject*)e).tag

答案 1 :(得分:2)

这里似乎存在一些关于属性和点符号的误解。点表示法可以与任何访问器方法一起使用,无论是否声明为属性,前提是编译器知道点左侧的对象具有访问器。您不需要使用@property语法。您不需要合成访问者。以下是完全有效的Objective-C,可以干净地编译:

#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;
}

关键点是编译器必须知道对象是否存在访问者,这意味着对象必须正确键入(即不能是id)。

答案 2 :(得分:1)

您可以使用提供的obj.prop getter语法(handwavily)编译器具有方法调用[obj prop]的原型,并提供setter语法[obj setProp:blah]。这意味着您可以将它用于NSNumberFormatter这样的类,它们不声明属性。这是否可取是值得商榷的。

如果您不介意所有括号,可以使用((Foo *)obj).prop将其强制转换为正确的对象类型。

请注意,未知方法的返回类型默认为id(因此您可能将id与int进行比较),并且您的发送方可能不是UIView(它可能是UIBarButtonItem)。如果您认为if ([(id<NSObject>)e isKindOfClass:[UIView class]] && [(UIView*)e tag] == sometag)符合&lt; NSObject&gt;,那么e会更安全一些。

答案 3 :(得分:0)

您不能在id对象上使用点表示法。这只是他们的规则。

答案 4 :(得分:0)

这是杰克在我评论之前删除了他的答案: - )

您不是直接访问实例变量,点符号仅用于通过@synthesized的getter和setter方法获取属性。您正在向对象发送消息,在这种情况下会导致调用这些getter / setter方法。您不能使用点表示法直接访问成员变量,也不能直接调用方法 - 必须将其设置为属性。