将自定义结构中的值设置为Objective-C中的属性

Log*_*gan 6 objective-c

我有一个带有标题的A类看起来像这样:

typedef struct {
    int x;
    int y;
} Position;

@interface ClassA : NSObject

@property Position currentPosition;

@end
Run Code Online (Sandbox Code Playgroud)

我尝试在另一个类中为属性分配位置结构的各个值,如下所示:

ClassA * classA = [ClassA new];
classA.currentPosition.x = 10;
Run Code Online (Sandbox Code Playgroud)

这给出了错误"表达式不可分配"并且不会编译.

我可以像这样设置:

ClassA * classA = [ClassA new];
Position position = {
    .x = 1,
    .y = 2
};

classA.currentPosition = position;
Run Code Online (Sandbox Code Playgroud)

我甚至可以改变position变量的各个"属性",如下所示:

ClassA * classA = [ClassA new];
Position position = {
    .x = 1,
    .y = 2
};

// WORKS
position.x = 4;    

// DOESN'T WORK
// classA.currentPosition.x = 4;

classA.currentPosition = position;
Run Code Online (Sandbox Code Playgroud)

为什么我不能在属性时单独设置值?

adp*_*mbo 6

这个表达式:

classA.currentPosition
Run Code Online (Sandbox Code Playgroud)

返回结构的临时副本,而不是结构本身.编译器错误告诉您无法为该临时副本的某个成员分配值(因为从rvalue技术上讲它是一个).但是你不想为这个成员分配一个值,因为它会随着struct本身一起消失.

那么为什么你只是首先得到结构的副本?

因为

@property Position currentPosition
Run Code Online (Sandbox Code Playgroud)

实际上只是简写:

-(Position)currentPosition;
-(void)setCurrentPosition(Position value);
Run Code Online (Sandbox Code Playgroud)

在C系列语言中,第一行(getter)表示它返回一个Position结构的值,或者作为副本.

您可以创建自己的访问者来返回引用,但您可能不应该这样做.这不是Objective-C中常见的习语 - 至少在这种情况下不是这样 - 你通常应该尝试坚持使用语言的常用习语.

相反,你应该使用如下的位置;

Position pos = classA.position;
pos.x = 4;
classA.position = pos;
Run Code Online (Sandbox Code Playgroud)

最后,如果您真的希望能够使用您最初需要的语法设置currentPosition,那么在维护Objective-C习语时,您可以将Position设为类而不是结构.然后,该属性可以返回a Position *,其余的语法将起作用.确保在函数中初始化指针init(或在适当的时候).