【问题标题】:Explanation of Objective-C propertiesObjective-C 属性的解释
【发布时间】:2012-02-21 05:02:58
【问题描述】:

我正在阅读一本关于 iOS 的书(它称为 Programming iOS 4,作者是 Matt Neuburg),在他解释属性的段落中,他说了这些话:

Objective-C 对属性使用点表示法,而 C 对结构使用点表示法;这些可以链接。因此,例如,UIView 的 frame 是一个属性,其值为一个结构(一个 CGRect);因此,您可以说 myView.frame.size.height,其中 frame 是返回结构的属性,size 是该结构的组件,height 是该结构的组件。但是 struct 不是指针,因此您不能(例如)直接通过以 UIView 开头的链来设置框架的高度,如下所示:

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

相反,如果您想更改结构属性的组件,您可以 必须将属性值提取到结构变量中,更改 struct 变量的值,并从 结构变量:

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

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

myView.frame.size.height = 36.0;

【问题讨论】:

标签: objective-c ios


【解决方案1】:

背景

编程语言中的变量是一个,它有一个名称(根据语言,有时称为“引用”或“指针”)。这个框包含某种类型的值。值不会改变,框的内容会改变。例如在以下代码中:

int a = 4;
a = 5;

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

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

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

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

函数sqrt 不是传递a,而是存储在a 中的 - 这是一些代表数字9.0 的位序列; sqrt 返回的是一些代表 3.0 的位序列,这些位存储在 b 中。传递的位,您在其中一个 cmets 中使用您的话,是“真正的价值”。

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

NSWindow *main = [NSApp mainWindow];

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

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

回答

在您的示例中,myView.frame 是一个属性,并且一个属性是使用方法实现的。在 Objective-C(和 C、C++)中,struct 类型是 value 类型 - 它被视为整数和浮点数,它的值被传递并存储在盒子中。因此,使用您的话,该属性返回的是“真正的结构” - 它与上面示例中表示 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]
    

    它会返回结构的 副本,而不是返回“真实”结构的指针。因此,编译器通过不允许您在临时结构中设置不会反映在“真实”结构中的值来帮助您。

    【讨论】:

    • 谢谢伙计。因此,即使我使用float height = myView.frame.size.height,它也会返回框架结构的副本而不是真实的? (在这种情况下没关系,因为值是相同的)
    • 你能告诉我为什么[myView frame][self myStruct] 给我一个结构的副本而不是真正的结构吗?
    • 这就是属性为数据值工作的方式,它们进行复制。否则,当您返回一个值时,您必须撤消指针引用以获取类似 int 或 struct 的东西,并且很多东西可能会被修改并产生意想不到的副作用。
    【解决方案3】:
    myView.frame
    

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

    【讨论】:

    • 感谢您的链接。但是为什么结构不能是左值呢?
    • @Fred:可以,但在这种情况下不是。
    • @JeremyP 好的,但在这种情况下为什么不呢?
    • @Fred:因为它只是一个可以在表达式中使用的临时 C 对象。这类似于尝试分配给 any 函数返回结果,例如foo(5) = 10(其中 foo 是一个返回 int 的函数)显然是无稽之谈,对于这个例子也是如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多