2012-02-21 68 views
3

我读一本书的iOS(它调用编程的iOS 4,由马特·诺伊堡),并在该段,他解释说,他说的属性这样的话:Objective-C的属性说明

的Objective-C对属性使用点符号,C对结构使用点符号;这些可以被链接。所以,例如,UIView的框架是一个属性,它的值是一个struct(一个CGRect);因此,可以说myView.frame.size.height,其中frame是返回结构的属性,size是该结构的一个组件,height是该结构的一个组件。但是,结构是不是指针,所以你不能(例如)通过链条直接设置框的高度开始UIView的,就像这样:

myView.frame.size.height = 36.0; // compile error 

相反,如果你想改变一个一个结构属性的组件,你必须 获取属性值到一个结构体变量,改变 结构变量的值,并从 结构变量设置整个属性值:

CGRect f = myView.frame; 
f.size.height = 0; 
myView.frame = f; 

我不太明白,为什么我不能使用下面的行?

myView.frame.size.height = 36.0; 
+1

看到这个[答案](http://stackoverflow.com/a/5861985/165737)。 – Anurag 2012-02-21 05:11:21

+2

[CGRect是一个实例变量时如何获得CGRect元素的赋值访问权限]的可能重复(http://stackoverflow.com/questions/5860755/how-to-gain-assignment-access-to-cgrect-elements-当这个cgrect是一个实例) – Costique 2012-02-21 05:20:44

回答

3

背景

在编程语言中的变量是一个具有名称(有时称为“参考”或取决于语言一个“指针”)。此框。包含了一些类型的值价值观不改变,盒子的内容做如下面的代码:

int a = 4; 
a = 5; 

第二行不改变4,它改变框a中的内容。

类型的编程语言可分为两类:值类型引用类型

对于值类型,传递和存储在框中的值是实际值的表示,例如,中的代码:

double a = 9.0; 
double b = sqrt(a); 

功能sqrt不传递a存储在a - 这是代表​​数目9.0位的一些序列; sqrt返回的是一些代表3.0的位序列,这些位存储在b中。在你的评论中使用你的单词的传递位是“真正的价值”。

对于引用类型,在盒子中传递和存储的是包含实际值的盒子名称(内存块)的一些表示。在Objective-C中,引用类型通过在其声明中使用*来区分(其他语言不需要*,例如Java & C# - 它们知道哪些类型是基于它们类型的引用类型)。 E.g代码:

NSWindow *main = [NSApp mainWindow]; 

的方法调用不返回窗口值本身,而是包含窗口值框的名称。再次使用你的话,“真正的价值”永远不会传递,而是包含该值的盒子的名字被传递。

传统上,“小”类型由值类型表示 - 整数,浮点数,字符等;而“参考”类型的“大”值。然而,每种编程语言都有自己的选择 - 有些甚至定义为只能使用引用类型。

回答

在您的例子myView.frame是一个属性,属性是使用一种方法来实现。在Objective-C(和C,C++)中,一个struct类型是一个类型 - 它被视为与整数和浮点数类似,它的值被传递并存储在框中。所以属性返回的是用你的话来说,“真实结构” - 它和上面例子中代表3.0的位一样“真实”。

什么是不返回是包含一个结构值的框的名称,并没有访问一个框你不能改变它的内容。这就是为什么myView.frame.size.height = 36.0;不正确 - 你试图改变一部分值,并且值不会改变。

但是给定一个NSRect框,您可以更改其部分内容。例如。中的代码:

NSRect aRect; 
aRect.size.height = 36.0; 

.size.height被识别,以改变所述盒aRect的一部分,和36.0的表示被存储到箱的部分。

HTH

2

因为如果你打破了这一切,myView.frame是等于说

CGRect aFrame = [myView frame] 

它给你回结构的副本,不是指针回到“真正的“结构。因此,编译器通过不让你在一个临时结构中设置一个不会反映在“真实”结构中的值来帮助你。

+0

谢谢你。所以即使当我使用'float height = myView.frame.size.height'时,它会返回frame结构的一个副本,而不是真实的结构? (在这种情况下它是可以的,因为值是相同的) – 2012-02-21 05:43:24

+0

你能告诉我为什么'[myView frame]'或'[self myStruct]'给了我一个结构的副本,而不是真正的结构? – 2012-02-21 06:05:22

+0

这就是属性如何工作的数据值,他们复制。否则,当你得到一个值时,你必须撤销指针引用才能得到类似于int或struct的东西,并且许多事情可能会被意外的副作用修改。 – 2012-02-21 06:50:00

1
myView.frame 

将返回一个结构,它是一个Rvalue而不是Lvalue。对于rvalue and lvalue read this
现在myView.frame将返回一个数据而不是指针的右值。

+0

感谢您的链接。但为什么一个结构不能是一个左值? – 2012-02-21 06:06:40

+0

@Fred:可以,但不是在这种情况下。 – JeremyP 2012-02-21 11:48:56

+0

@JeremyP好的,但为什么不在这种情况下? – 2012-02-21 20:05:15