быстрые глобальные константы: нельзя использовать другую константу для инициализации

Вот что я пытаюсь сделать:

class ViewController: UIViewController {
let screenRect: CGRect = UIScreen.mainScreen().bounds
let screenWidth = screenRect.width;
let screenHeight = screenRect.height;
let screenX = screenRect.origin.x
let screenY = screenRect.origin.y
override func viewDidLoad() {
...and so on

Swift позволяет мне объявить screenRect.

Однако это не позволяет мне объявлять какие-либо другие константы, используя это. Он показывает мне ошибку: 'ViewController.Type' does not have a member named 'screenRect'

Как мне определить эти константы и почему swift не позволяет мне использовать другую константу для их определения.


person Nikita P    schedule 09.07.2014    source источник


Ответы (3)


Константы ничего не знают о других глобальных константах, потому что в этот момент они не инициализированы. Однако вы можете использовать вычисляемые свойства:

class ViewController: UIViewController {
  var screenRect: CGRect { return UIScreen.mainScreen().bounds }
  var screenWidth: CGFloat { return self.screenRect.origin.x }
}

Это работает только с vars из-за его природы. Это следует учитывать в зависимости от варианта использования. Если вам приходится вызывать его часто, это может быть не самый мудрый способ с точки зрения производительности.

person artey    schedule 09.07.2014

Невозможно получить доступ к self до завершения процесса инициализации, поэтому выдается ошибка.

person Yatheesha    schedule 09.07.2014

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

Мое предложение состоит в том, чтобы переместить инициализацию свойств в метод init().

Дополнение 1: как предложил @Yatheesha, правильно сказать, что self недоступен, пока все свойства не будут инициализированы — см. параграф «Двухфазная инициализация» в быстром книга, в разделе "Инициализация"

В этой строке (как и в следующих за ней):

let screenWidth = screenRect.width;

вы неявно используете self.

Таким образом, правильно использовать init() следующим образом:

let screenRect: CGRect
let screenWidth: NSNumber
let screenHeight: NSNumber
let screenX: NSNumber
let screenY: NSNumber

init(coder aDecoder: NSCoder!) {
    let bounds = UIScreen.mainScreen().bounds
    screenRect = bounds
    screenWidth = bounds.width
    screenHeight = bounds.height
    screenX = bounds.origin.x
    screenY = bounds.origin.y

    super.init(coder:aDecoder)
}

Конечно, если есть более одного назначенного init(), вы должны реплицировать этот код на каждом. В этом случае может быть лучше использовать подход @Andy с использованием вычисляемых свойств, если вы предпочитаете избегать дублирования кода.

Приложение 2

Еще один очевидный способ (и, возможно, лучший) — вообще избегать использования self:

let screenRect: CGRect = UIScreen.mainScreen().bounds
let screenWidth = UIScreen.mainScreen().bounds.width;
let screenHeight = UIScreen.mainScreen().bounds.height;
let screenX = UIScreen.mainScreen().bounds.origin.x
let screenY = UIScreen.mainScreen().bounds.origin.y
person Antonio    schedule 09.07.2014
comment
Swift, по-видимому, также не позволяет определять константы буквальными константами, например: let secondsPerMinute: Int = 60; пусть минуты в час: Int = 60; пусть секунды в час: Int = секунды в минуту * минуты в час не удастся - person rockhammer; 20.06.2016
comment
@rockhammer Я попробовал этот код на детской площадке, и он работает - person Antonio; 20.06.2016
comment
На детской площадке не пробовал. Xcode перестает компилироваться, когда видит это, во всяком случае для меня - person rockhammer; 20.06.2016