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

ⅰ亾dé卋堺 提交于 2019-12-10 16:43:06

问题


This question is inspired by Andrew Carter's comment on a previous question about the new CGSize initializer in Swift.

The Apple Docs for CGGeometry say:

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

Is Apple's recommendation to not directly access the data in a CGRect still valid with Swift? Why should CGRectGetMidX, CGRectGetWidth, etc. be used in place of accessing the values of a CGRect struct directly, when these properties are now exposed with Swift's new extension on CGRect?


回答1:


Consider a non-standard CGRect with a negative width and height:

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

This is a valid rectangle according to the Apple docs, as "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]."

You can standardize this CGRect by calling the legacy inline CGRectStandardize method like in Objective-C, or any of the new methods provided on the Swift extension of 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}

But wait! This will reposition your rect on the coordinate plane, not only making your width and height positive, but making your origin negative to reflect the initial position of the rect with its negative width and height.

The inline CGRectGet functions provide an interface to normalize a specific value of your rect, without changing its origin. Swift provides an extension on CGRect so you can access the normalized values directly, rather than using the legacy C methods provided by CGGeometry:

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

The new interfaces:

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 }
    // ...
}

So the answer is yes, the same rules for CGRect in Objective-C apply in Swift as well. The only difference here is that Swift provides an extension on some CGGeometry structs which allow you to move away from the old inline C functions bridged from the CGGeometry headers.




回答2:


In Swift 3, it looks like CGRectGetWidth() is replaced by CGRect.width.



来源:https://stackoverflow.com/questions/35608638/accessing-cgrect-values-directly-vs-normalizing-them-in-swift-objective-c-rule

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!