Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone Obj-C中[object variable]和object.variable之间的差异?_Iphone_Objective C_Cocoa_Xcode - Fatal编程技术网

Iphone Obj-C中[object variable]和object.variable之间的差异?

Iphone Obj-C中[object variable]和object.variable之间的差异?,iphone,objective-c,cocoa,xcode,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-cla

我今天在做一个程序,遇到了一个奇怪的错误。我有一个带有指定动作的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*'
但我认为这两者是等价的


那么在什么情况下它们是不一样的呢?

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

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

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

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

您可以将对象强制转换为您期望的类型,这将允许您使用属性语法

((MyObject*)e).tag

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


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

可以使用提供的obj.prop getter语法(手动),即编译器具有方法调用的原型[obj prop],以及提供的setter语法[obj setProp:blah]。这意味着您可以将它用于像NSNumberFormatter这样不声明属性的类。这是否明智尚待讨论

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


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

这里似乎对属性和点符号有一些误解。点表示法可用于任何访问器方法,无论是否声明为属性,只要编译器知道点左侧的对象具有访问器。您不需要使用
@属性
语法。您不需要合成访问器。以下是完全有效的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;
}
#导入
@接口类
{
}
-(NSString*)属性;
@结束
@实现AClass
-(NSString*)属性
{
返回@“一些文本”;
}
@结束
int main()
{
AClass*foo=[[AClass alloc]init];
NSLog(@“%@”,食品属性);
返回0;
}

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

我是objective-c noob。。。好问题,我不知道。不过这是有道理的。谢谢你的帮助,这是错误的。您可以对任何声明的访问器方法使用点表示法,无论是声明为属性还是方法/方法对。是的,Kenny,您是正确的。我的原始版本是从tag属性强制转换返回值,而不是强制转换
e
对象。谢谢。为什么点符号不限于@property声明的访问器?它似乎解决了模棱两可的情况(例如,
.uppercaseString
),并允许类作者让编译器强制执行它们的意图。有技术或哲学上的原因吗?@Preston:我不知道你说的含糊不清的情况是什么意思。在我看来,
uppercaseString
应该做什么并不含糊。能够使用点符号调用
-uppercaseString
,意味着它是一个属性。@Preston:不。提示您输入的是选择器的名称,而不是其他任何东西,也不可能是。即使点表示法仅限于使用
@property
声明的选择器,我仍然可以创建一个名为saveFileToDisk的“属性”或其他操作。在该示例中,作为类作者,您的意图是有一个名为
safeFileToDisk
的名称不正确的属性,并且可以在点表示法中调用它。现在,编译器不能保证您在点表示法中调用的是一个属性。