-1

I am working on iOS code with Xcode 10.2.1.

I have an issue when declaring a let global variable:

import UIKit

import CouchbaseLiteSwift

private let database: Database

This gives the compiler error below:

Global 'let' declaration requires an initializer expression

I don't know how to make database a global variable in this case. I searched about it, but all says about some int or string initialization but not when initializing classes like Database. Because, Couchbase's Database class is a big class. I can't do it with "= null"

Any help please?

Paul Cantrell
  • 9,175
  • 2
  • 40
  • 48
Stella
  • 1,728
  • 5
  • 41
  • 95
  • 2
    You need an `=` followed by some appropriate initialization. – rmaddy May 16 '19 at 00:41
  • Do you want a global variable (as you state) or a global constant? A let is a constant, so you have to give it an initial value at declaration (e.g. `private let database: Database = Database()`, or just `private let database = Database()`. If you want a variable then make it `var`. Everything you found whilst searching is correct, even if talking about an int or string. – Chris Shaw May 16 '19 at 00:43
  • I tried both, but it says "Missing argument for parameter 'name' in call" – Stella May 16 '19 at 00:44
  • 1
    Basically, just change it to be `private let database: Database?` – zaitsman May 16 '19 at 00:44
  • private let database: Database? didn't work either. Same error Global 'let' declaration requires an initializer expression – Stella May 16 '19 at 00:45
  • @Stella Given the error, clearly you need something like `= Database(name: someNameHere)`. Look at the documentation for this `Database` class. – rmaddy May 16 '19 at 00:53

2 Answers2

4

You need a variable if you're not sure what it is so that later you can change it:

private var database: Database?

There's no point in defining a constant if you're not going to actually define it as something.

tadman
  • 208,517
  • 23
  • 234
  • 262
1

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!
Paul Cantrell
  • 9,175
  • 2
  • 40
  • 48