Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot convert value of type '() -> _' to specified type UIImageView

I am trying to make a UIImage view clickable, but I am having no luck. What is the best way to complete this task? The error I am getting is "Cannot convert value of type '() -> _' to specified type 'UIImageView'".

lazy var profileImageView: UIImageView = {
     let imageView = UIImageView()
     imageView.image = UIImage(named: "ic_file_upload_white_48pt")
     imageView.translatesAutoresizingMaskIntoConstraints = false
     imageView.contentMode = .scaleAspectFill

     imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleSelectorProfileImage)))
     imageView.isUserInteractionEnabled = true
     return imageView
 }
like image 709
Jameel Avatar asked Mar 10 '17 23:03

Jameel


3 Answers

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:

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:

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
}

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.

like image 118
Duncan C Avatar answered Nov 06 '22 19:11

Duncan C


Looks like a syntax issue, try

func profileImageView() -> UIImageView {
        let imageView = UIImageView()
        imageView.image = UIImage(named: "ic_file_upload_white_48pt")
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .scaleAspectFill

        imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleSelectorProfileImage)))
        imageView.isUserInteractionEnabled = true
        return imageView
}
like image 43
jokeman Avatar answered Nov 06 '22 19:11

jokeman


You should add paranthesis after the end of computed property in order to execute it.

lazy var profileImageView: UIImageView = {
     let imageView = UIImageView()
     imageView.image = UIImage(named: "ic_file_upload_white_48pt")
     imageView.translatesAutoresizingMaskIntoConstraints = false
     imageView.contentMode = .scaleAspectFill

     imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleSelectorProfileImage)))
     imageView.isUserInteractionEnabled = true
     return imageView
 }()
like image 6
Mukesh Shakya Avatar answered Nov 06 '22 18:11

Mukesh Shakya