简体   繁体   中英

swift global constants: cannot use another constant for initialization

Here is what I am trying to do:

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 allows me to declare screenRect .

However, it does not allow me to declare any other constants using this. It shows me the error: 'ViewController.Type' does not have a member named 'screenRect'

How do I define these constants and why does not swift allow me to use another constnt to define them.

在初始化过程完成之前无法访问自身 ,因此它给出错误。

The consts do not know about the other global consts because they are not initialized at this point. What you could do though is to use computed properties:

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

This only works with vars, due to the nature of it. This should be considered depending on the use case. If you have to call it often, it might not be the wisest way in regards to performance.

What probably happens is that during instantiation and initialization it's not guaranteed that properties are initialized in the same order as you have defined them in the code, so you cannot initialize a property with a value retrieved from another property.

My suggestion is to move the property initializations in the init() method.

Addendum 1 : as suggested by @Yatheesha, it's correct to say that self is not available until all properties have been initialized - see "Two-Phase Initialization" paragraph in the swift book, under "Initialization"

In this line (as well as in the ones after it):

let screenWidth = screenRect.width;

you are implicitly using self .

So the correct way is to use init() as follows:

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)
}

Of course if there is more than one designated init() , you have to replicate that code on each. In that case it might be better to use @Andy's approach, using computed properties, if you prefer to avoid code duplication.

Addendum 2

Another obvious way (and probably the best one) is to avoid using self at all:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM