You are telling the compiler that you want to make profileImageView
contain a closure. If you want profileImageView to contain the results of that closure, you need to add parens after in order to invoke the closure:
lazy var profileImageView: UIImageView = {
//your code here
return imageView
}()
Note the parentheses after the closure. That assigns the result of calling the closure to your variable profileImageView
the first time you reference the variable.
Edit:
Any time you see a type of (<something>) -> type
it's a closure. The ->
bit separates the parameters from the return type. Swift's error messages can be hard to decipher, but that's a clue that you're returning a closure rather than whatever is expected.
Edit #2:
Note that there are 2 similar constructs related to a variable defined by a closure in Swift: Computed properties and lazy variables.
Computed properties
A computed property is declared as
var computed: type { closure_returning_result }
There is no equals sign in a computed property. Every time you ask for a value from the computed property, the closure code runs, and the returned value of the closure is the new value of the property.
Lazy vars:
A lazy var looks like this:
lazy var lazy: type = expression_returning_result
The expression is often a closure, but it doesn't have to be. A common form of a lazy var would use a closure, like this:
lazy var lazy: type = { closure_returning_result }()
There is an equals sign in the declaration of a lazy var. If you use a closure to assign a value to a lazy var, you need to add parentheses after the closure, so the lazy var is assigned the returned value of the closure, not the closure itself. This thread came up when @jameel forgot the closing parentheses in his code.
Consider the following code:
var counter = 1
var computed: Int {
counter += 1
return counter
}
lazy var lazy: Int = {
counter += 1
return counter
}()
print("lazy = \(lazy)")
print("lazy = \(lazy)")
print("lazy = \(lazy)")
print("computed = \(computed)")
print("computed = \(computed)")
print("computed = \(computed)")
That prints the output:
lazy = 2
lazy = 2
lazy = 2
computed = 3
computed = 4
computed = 5
Note that the value of the lazy var doesn't change, but the value of the computed property does. That is the key difference between them.
A lazy variable gets evaluated once the first time you ask for it, and that value "sticks". The expression/closure that gives the value is not run until you ask for it, and then only once.
In contrast, a computed property always uses a closure, and every time you ask for the value of a computed property, the closure is executed.
Edit #3: (9/28/2023)
Also note that the fact that a lazy variable isn't initialized until you first reference it can have consequences.
If you reversed the order of the test code above:
print("computed = \(aFoo.computed)")
print("computed = \(aFoo.computed)")
print("computed = \(aFoo.computed)")
print("lazy = \(aFoo.lazy)")
print("lazy = \(aFoo.lazy)")
print("lazy = \(aFoo.lazy)")
print("computed = \(aFoo.computed)")
print("lazy = \(aFoo.lazy)")
print("computed = \(aFoo.computed)")
The output would be
computed = 2
computed = 3
computed = 4
lazy = 5
lazy = 5
lazy = 5
computed = 6
lazy = 5
computed = 7
With that sample code, we don't reference lazy
until after we've invoked our computed property 3 times. As soon as we reference lazy
, it increments counter
and saves that result as its new value, FOREVER.
If we then reference computed
again, it again increments counter.
lazy
's value is stuck at 5 for the lifetime of this execution of the code.