直接访问 CGRect 值与在 Swift 中规范化它们相比 - Objective-C 规则仍然有效?

Accessing CGRect values directly vs normalizing them in Swift - Objective-C rules still valid?

这个问题的灵感来自 上一个关于 Swift 中新的 CGSize 初始值设定项的问题。

Apple Docs for CGGeometry 说:

... your applications should avoid directly reading and writing the data stored in the CGRect data structure. Instead, use the functions described here to manipulate rectangles and to retrieve their characteristics.

Apple 关于不直接访问 CGRect 中的数据的建议对于 Swift 是否仍然有效?为什么要使用 CGRectGetMidXCGRectGetWidth 等来代替直接访问 CGRect 结构的值,而这些属性现在通过 Swift 的新扩展公开在 CGRect?

考虑具有负宽度和高度的 non-standard CGRect

var rect = CGRect(x: 0.0, y: 0.0, width: -10.0, height: -10.0)

根据 Apple 文档,这是一个有效的矩形,因为 "a rectangle with an origin of [0.0, 0.0] and a size of [10.0, 10.0] is exactly equivalent to a rectangle with an origin of [10.0, 10.0] and a size of [-10.0, -10.0]."

您可以通过调用 Objective-C 中的旧内联 CGRectStandardize 方法或 Swift 扩展中提供的任何新方法来标准化此 CGRect CGRect:

CGRectStandardize(rect) // {x -10 y -10 w 10 h 10}
rect.standardized // {x -10 y -10 w 10 h 10}
rect.standardizeInPlace() // {x -10 y -10 w 10 h 10}

但是等等! 这将在坐标平面上重新定位您的矩形,不仅使您的宽度和高度为正,而且使您的 origin 为负以反映初始值具有负宽度和高度的矩形的位置。

内联 CGRectGet 函数提供了一个接口,可以在不更改其原点的情况下规范化矩形的特定值。 Swift 在 CGRect 上提供扩展,因此您可以直接访问规范化值,而不是使用 CGGeometry:

提供的遗留 C 方法
var rect = CGRect(x: 0.0, y: 0.0, width: -10.0, height: -10.0)

rect.size.width // non-normalized, returns -10
CGRectGetWidth(rect) // bridged C function, normalized, returns 10
rect.width // new from Swift extension on CGRect, normalized, returns 10

新界面:

extension CGRect {
    // ...
    public var width: CGFloat { get }
    public var height: CGFloat { get }
    public var minX: CGFloat { get }
    public var midX: CGFloat { get }
    public var maxX: CGFloat { get }
    public var minY: CGFloat { get }
    public var midY: CGFloat { get }
    public var maxY: CGFloat { get }
    // ...
}

所以答案是肯定的,Objective-C 中 CGRect 的相同规则也适用于 Swift。这里唯一的区别是 Swift 提供了对某些 CGGeometry 结构的扩展,它允许您摆脱从 CGGeometry headers.[= 桥接的旧内联 C 函数。 29=]

在Swift3中,CGRectGetWidth()好像被CGRect.width代替了。