Этот вопрос навеян Комментарий Эндрю Картера на предыдущий вопрос о новом инициализаторе CGSize в Swift.

В Apple Docs для CGGeometry говорится:

... ваши приложения должны избегать прямого чтения и записи данных, хранящихся в структуре данных CGRect. Вместо этого используйте функции, описанные здесь, для управления прямоугольниками и получения их характеристик.

Верна ли рекомендация Apple не обращаться к данным в CGRect напрямую со Swift? Почему следует использовать CGRectGetMidX, CGRectGetWidth и т. Д. Вместо прямого доступа к значениям структуры CGRect, если эти свойства теперь доступны с новым расширением Swift на CGRect ?

4
JAL 24 Фев 2016 в 20:12

2 ответа

Лучший ответ

Рассмотрим нестандартный CGRect с отрицательными шириной и высотой:

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

Согласно документам Apple, это допустимый прямоугольник, поскольку «прямоугольник с началом координат [0.0, 0.0] и размером [10.0, 10.0] в точности эквивалентен прямоугольнику с началом координат [10.0, 10.0] и размер [-10.0, -10.0]. "

Вы можете стандартизировать этот CGRect, вызвав унаследованный встроенный метод CGRectStandardize, как в Objective-C, или любой из новых методов, представленных в расширении Swift для 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, поэтому вы можете напрямую обращаться к нормализованным значениям, а не использовать устаревшие методы C, предоставляемые 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

Новые интерфейсы:

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

Итак, да, те же правила для CGRect в Objective-C применяются и в Swift. Единственная разница в том, что Swift предоставляет расширение для некоторых структур CGGeometry, которое позволяет вам отойти от старых встроенных функций C, соединенных мостом из заголовков CGGeometry.

8
JAL 24 Фев 2016 в 17:20

В Swift 3 похоже, что CGRectGetWidth() заменен на CGRect.width.

enter image description here

1
Genki 4 Май 2017 в 23:12