Objective-C 结构体属性指针无法通过 self.prop 生成?
我刚刚在将 NSCoder 支持写入类时遇到了一点惊喜。我有一个 A 类,其中包含 RGB 结构类型的公开“颜色”属性。我有另一个扩展 A 的类 B。
为了在类 B 的encodeWithCoder 方法中对颜色属性进行编码,我首先将其包装到 NSValue 中,如下所示:
[NSValue value:&(self.color)]
但是使用此代码会导致以下编译错误:
Lvalue required as unary '&' operand.
只需复制即可轻松解决在用 NSValue 包装之前将 self.color 更改为方法范围值,但我想了解何时发生这种情况以及为什么会发生的规则。任何 @synthesize 属性是否会发生这种情况,因为不需要存在该属性名称的真实类字段,因此没有保证指向的对象?
I've just encountered a little surprise whilst writing NSCoder support into a class. I have a class A which contains an exposed 'color' property of an rgb struct type. I have another class B which extends A.
To encode the color property within class B's encodeWithCoder method I've first wrapped it into an NSValue like so:
[NSValue value:&(self.color)]
However using this code causes the following compilation error:
Lvalue required as unary '&' operand.
It's easy enough to get around by simply copying self.color to a method-scope value before wrapping with NSValue, but I'd like to understand the rule for when this will happen, and why it occurs. Will this happen with any @synthesize property due to there being no need for a true class field of that property name to exist, hence no guaranteed object to point to?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您无法获取函数(或方法)返回的内容的地址。您需要直接获取
color
ivar的地址(即&color
)。不过,就您而言,我建议使用您自己提出的方法(id tempCol = self.color; [NSValue value:&tempCol];
)。请注意,使用点表示法时会调用方法。
&([self color])
也是不可能的,因为&
是在编译时解析的,而不是在运行时解析的。[self color]
和self.color
(相等)的返回值在编译时尚不知道(即使使用@synthesize< /code>,因为您可以在运行时更改 Objective-C 中方法的实现(例如使用方法混合或使用类别)。
看来你还没有完全理解
@synthesize
的作用,所以我来解释一下。 :)基本上,
@synthesize
的作用是:编译器根据给定的属性名称生成方法及其实现。例如,这个属性:
与这个合成一起:
将在
@implementation
中为您插入这段代码:当您喜欢使用自己的 setter 或 getter 时,您只需在
@ 中定义它们即可使用相同的方法名称实现
。例如,如果尚未设置,您可以返回默认颜色:现在编译器将生成 setter,但不会生成 getter:它将使用您提供的 getter,您仍然可以将其与 self.color 一起使用/代码>。
您可能需要查看 Apple 指南关于属性。
You cannot get the address of something returned by a function (or method). You need to get the address of the
color
ivar directly (i.e.&color
). In your case though, I recommend using the approach you proposed yourself (id tempCol = self.color; [NSValue value:&tempCol];
).Note that a method is invoked when using dot notation.
&([self color])
is also impossible because&
is resolved at compile-time, not at runtime. The return value of[self color]
andself.color
(which are equal) aren't yet known at compile-time (even when using@synthesize
, since you can change a method's implementation in Objective-C at runtime (e.g. with method swizzling or using categories)).It seems that you don't fully understand what
@synthesize
does, so I'll explain. :)Basically what
@synthesize
does is this: the compiler generates methods and their implementations from the given property names.For example, this property:
Together with this synthesization:
Will insert this code for you in the
@implementation
:When you like to use your own setter or getter, you simply define these in the
@implementation
by using the same method names. You could, for example, return a default color if none is set yet:Now the compiler will generate the setter, but not the getter: it will use the getter you provided, you can still use it with
self.color
.You may want to take a look at Apple's guide on properties.
规则很简单。编译器将属性访问:
转换为方法调用*
,这意味着
&(self.color)
变成&([self color])
。然后编译器会抱怨,因为你无法获取方法调用的地址。*如果您要分配给属性,则分配将转换为对设置器的调用:
self.color = aColor;
->[self setColor:aColor];
。The rule is simple enough. The compiler turns a property access:
into a method call*
which means that
&(self.color)
turns into&([self color])
. Then the compiler complains, because you can't take the address of a method call.*If you were assigning to the property, the assignment would be transformed into a call to the setter:
self.color = aColor;
->[self setColor:aColor];
.