Objective-C 结构体属性指针无法通过 self.prop 生成?

发布于 2024-11-30 05:04:02 字数 445 浏览 0 评论 0原文

我刚刚在将 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陪你搞怪i 2024-12-07 05:04:02

您无法获取函数(或方法)返回的内容的地址。您需要直接获取color ivar的地址(即&color)。不过,就您而言,我建议使用您自己提出的方法(id tempCol = self.color; [NSValue value:&tempCol];)。


请注意,使用点表示法时会调用方法。

self.color
// is equal to
[self color]

&([self color]) 也是不可能的,因为 & 是在编译时解析的,而不是在运行时解析的。 [self color]self.color (相等)的返回值在编译时尚不知道(即使使用 @synthesize< /code>,因为您可以在运行时更改 Objective-C 中方法的实现(例如使用方法混合或使用类别)。


看来你还没有完全理解 @synthesize 的作用,所以我来解释一下。 :)

基本上,@synthesize 的作用是:编译器根据给定的属性名称生成方法及其实现。

例如,这个属性:

@property(nonatomic, retain) NSColor *color;

与这个合成一起:

@synthesize color;

将在 @implementation 中为您插入这段代码:

- (NSColor *)color {
  return color;
}

- (void)setColor:(NSColor *)newColor {
  if (color == newColor) { return; }
  NSColor *theOldColor = color;
  color = [newColor retain];
  [theOldColor release];
}

当您喜欢使用自己的 setter 或 getter 时,您只需在 @ 中定义它们即可使用相同的方法名称实现。例如,如果尚未设置,您可以返回默认颜色:

- (NSColor *)color {
  if (color) { return color; }
  return [NSColor whiteColor];
}

现在编译器将生成 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 equal to
[self color]

&([self color]) is also impossible because & is resolved at compile-time, not at runtime. The return value of [self color] and self.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:

@property(nonatomic, retain) NSColor *color;

Together with this synthesization:

@synthesize color;

Will insert this code for you in the @implementation:

- (NSColor *)color {
  return color;
}

- (void)setColor:(NSColor *)newColor {
  if (color == newColor) { return; }
  NSColor *theOldColor = color;
  color = [newColor retain];
  [theOldColor release];
}

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:

- (NSColor *)color {
  if (color) { return color; }
  return [NSColor whiteColor];
}

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.

尴尬癌患者 2024-12-07 05:04:02

规则很简单。编译器将属性访问:

self.color

转换为方法调用*

[self color]

,这意味着 &(self.color) 变成 &([self color])。然后编译器会抱怨,因为你无法获取方法调用的地址。


*如果您要分配给属性,则分配将转换为对设置器的调用:self.color = aColor; -> [self setColor:aColor];

The rule is simple enough. The compiler turns a property access:

self.color

into a method call*

[self color]

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];.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文