【问题标题】:Why can't access view.center.x / y为什么无法访问 view.center.x / y
【发布时间】:2026-02-16 19:40:01
【问题描述】:

我只是好奇为什么你不能访问 view.center.x 或 view.center.y 但你可以访问 view.center 并更改它。

我想写这段代码:

imgView_.center = scrollView_.center;
if (imgView_.frame.origin.x < 0) 
    imgView_.center = CGPointMake(imgView_.center.x + (imgView_.frame.size.width - self.view.frame.size.width) / 2, imgView_.center.y);
if (imgView_.frame.origin.y < 0)
    imgView_.center = CGPointMake(imgView_.center.x, imgView_.center.y + (imgView_.frame.size.height - self.view.frame.size.height) / 2);

作为:

imgView_.center = scrollView_.center;
if (imgView_.frame.origin.x < 0) 
    imgView_.center.x = imgView_.center.x + (imgView_.frame.size.width - self.view.frame.size.width) / 2;
if (imgView_.frame.origin.y < 0)
    imgView_.center.y = imgView_.center.y + (imgView_.frame.size.height - self.view.frame.size.height) / 2;

我发现第二种方式更优雅,但我无法访问 x 和 y,所以我想问问是否有人知道 Apple 阻止它的原因是什么。

【问题讨论】:

标签: ios objective-c center


【解决方案1】:

查看UIView's UIViewGeometry 类别中定义的中心属性,如下所示

@property(nonatomic) CGPoint center;

通过声明中心属性,我们有 getter & setter 方法用于中心属性。这意味着我们有结构的 setter 和 getter 方法,而不是结构内的值。 而Center 是一个CGPoint 结构变量,它有两个CGFloatx 和y

这是因为我们不能直接在 center 属性中设置 x 和 y 值。它类似于 Frame 属性。

【讨论】:

  • @LordZsolt 除了混合 c 和 Objective-c 之外,主要原因之一是更新中心属性时需要更新计算属性(例如框架)。直接更改结构成员将跳过此更新
  • 我同意@wattson,有一些相关的属性需要在更新中心和框架等属性时自动更新,这就是为什么Apple没有提供任何直接设置坐标(X和Y)的链接.特别是在坐标相关属性的情况下,您可以看到这一点。
【解决方案2】:

UIView 属性center 是一个CGPoint,它的类型是struct,而不是一个ObjectiveC 类。

虽然写了这篇

view.center.x = view.center.x +10;

看起来很像

CGPoint center = view.center;
center.x = center.x +10;
view.center = center;

它们是不同的东西。

根据编译器view.center 是一个方法调用[view center]center.x 正在访问结构CGPoint 的公共ivar。如果您将所有这些都写在一行中

view.center.x = view.center.x +10;

编译器无法解决此问题并引发错误Expression is not assignable。原因是view.center.x被进一步解析为函数调用,

objc_msgSend(view, @selector(center))

现在您正在尝试修改 C 函数的返回值,如下所示

objc_msgSend(view, @selector(center)).x = 20 //(Some value on RHS) 

这没有意义,因为函数返回值没有存储在任何地方,因此结果表达式不可赋值。

更多信息请阅读this answer

希望有帮助!

【讨论】:

    【解决方案3】:

    在片段imgView_.center.x 中,.center 是一个属性 访问,而.x 是一个字段 访问。属性类型为CGPoint,是一个结构体类型,通过value传递。

    如果您有CGPoint 类型的变量,您可以直接分配给各个字段,例如:

    CGPoint myPoint;
    myPoint.x = 3;
    

    但是,当将 CGPoint 值传递给函数或方法时,您不能只传递其中一个字段 - 这没有任何意义。例如。如果你有这个功能:

    void doSomething(CGPoint aPoint);
    

    你可以通过myPoint:

    doSomething(myPoint);
    

    但是没有办法说“只通过x 字段”——这甚至意味着什么?该函数需要一个CGPoint,传递一个坐标意味着什么?

    当您将片段 imgView_.center 放在赋值的左侧时,您只是在使用简写来调用方法。例如:

    imgView_.center = myPoint; <=> [imgView_ setCenter:myPoint];
    

    就像上面的函数一样,没有办法说“只需传递x 字段”。

    关键点是属性访问不是变量访问,尽管它通常被认为是一个,而是一个函数/方法调用;所以你不能分配给结构类型属性的单个字段。

    在右侧访问属性的字段很好。例如。在右上方imgView_.center 转换为[imgView_ center] - 它返回一个CGPoint ,并且您可以访问结构值的字段,所以在右上方imgView_.center.x 转换为[imgView_ center].x 和一切正常。但请注意,在两种情况下(setCenter:center 方法),方法本身采用/返回一个完整CGPoint

    HTH。

    【讨论】: