The distinguishing feature of a let
variable is that it is assigned to exactly once before being read.
When a let
declaration is a local variable, Swift can analyze the code to make sure that the variable will be initialized exactly once before it is used. This is why you can declare a local let
variable with no initial value. For example:
let greeting: String
if(light.isOn()) {
greeting = "Hello!"
} else {
greeting = "Who’s there?!"
}
// Now it is OK to use greeting, because we _know_ the code took
// exactly one branch of the if, and each branch initializes greeting
print(greeting) // OK
With an instance variable, you don't need to specify an initial value as long as every initializer sets it exactly once.
However, with a global variable, the compiler can't really make any guarantees about who will assign to it when. You therefore have to give it an initial value right on the spot.
As @rmaddy points out in the comments, it might look like this:
private let database = Database(name: "foo")
If initialization takes multiple statements, you can batch them up in a closure like this:
private let database = {
let config = readConfigFile()
guard let dbName = config["database"] else {
fatalError("Missing config for 'database'")
}
return Database(name: dbName)
}()
If you must make it a global, but it just isn't possible to initialize it until later, you must make it a var
:
private var database: Database?
…or if you want any attempt to use it before it’s initialized to be a crasher:
private var database: Database!