swift глобални константи: не може да използва друга константа за инициализация

Ето какво се опитвам да направя:

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 не е наличен докато всички свойства не бъдат инициализирани - вижте параграфа „Двуфазна инициализация“ в swift книга, под "Инициализация"

В този ред (както и в тези след него):

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; нека secondsPerHour: Int = secondsPerMinute * minutesPerHour ще се провали - person rockhammer; 20.06.2016
comment
@rockhammer Опитах този код на детска площадка и работи - person Antonio; 20.06.2016
comment
Не съм пробвал на детска площадка. Xcode спира да компилира, когато види това, за мен така или иначе - person rockhammer; 20.06.2016