2010-06-10 74 views
3

我今天正在开发一个程序,并且遇到了这个奇怪的bug。我有一个分配了操作的UIButton。该行动是这样的:Obj-C中[object variable]和object.variable之间的区别?

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

什么让我困惑的是,当我第一次写吧,如果线是

if (e.tag==SOMETAG) 

的XCode拒绝编译它,说

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

但我认为这两者是相同的。

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

+0

我是一个objective-c noob ...很好的问题。 – codemonkey 2010-06-10 23:46:05

回答

5

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

当宣布财产时,someObject.variable相当于[someObject variable]

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

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

((MyObject*)e).tag 
+0

不知道。这很有道理。感谢您的帮助。 – jergason 2010-06-11 00:23:04

+2

这是错误的。您可以将点符号与任何*声明的* accessor方法一起使用,无论声明为属性还是方法/方法对。 – JeremyP 2010-06-11 09:46:58

+0

是的,你是对的。我会更新我的答案。 – Jasarien 2010-06-11 11:04:30

0

对id对象不能使用点符号。这只是他们的一个规则。

0

这是杰克谁删除了他的答案之前,我可以:-)

评论你不是直接访问实例变量,点号只用于在性能获得,通过吸气和你合成的setter方法。您正在向对象发送消息,在这种情况下会导致getter/setter方法被调用。您不能使用点符号直接访问成员变量,或者直接调用方法 - 必须将其设置为属性。

1

您可以使用obj.prop getter语法(handwavily)提供编译器具有方法调用[obj prop]的原型,并提供setter语法[obj setProp:blah]。这意味着你可以将它与NSNumberFormatter这类不声明属性的类一起使用。这是否可取是有争议的。

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

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

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

的关键点是,编译器必须知道如果存取器存在这意味着该对象必须键入正确的对象(即,可以” t是id)。

+0

为什么不将点符号限制为@属性声明的访问器?它似乎可以解决模棱两可的情况(例如'.uppercaseString'),并允许类作者使编译器强制执行它们的意图。是否有技术或哲学原因? – 2010-07-04 22:16:56

+0

@Preston:我不确定你对含糊情况的看法。对于'uppercaseString' *应该做什么来看,我似乎没有任何含糊之处。 – JeremyP 2010-07-05 07:31:15

+0

能够使用点符号调用'-uppercaseString'意味着它是一个属性。 – 2010-07-06 19:42:13

相关问题