我正在尝试使 UIImage 视图可点击,但我没有运气。完成这项任务的最佳方式是什么?我收到的错误是“无法将类型 '() -> _' 的值转换为指定类型 '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
}
您告诉编译器您想要使
profileImageView
包含一个闭包。如果您希望 profileImageView 包含该闭包的results,则需要在后面添加括号以调用闭包:
lazy var profileImageView: UIImageView = {
//your code here
return imageView
}()
注意结束后的括号。第一次引用变量时,会将调用闭包的结果分配给变量
profileImageView
。
任何时候你看到某种类型的
(<something>) -> type
都是一个闭包。 ->
位将参数与返回类型分开。 Swift 的错误消息可能很难解读,但这是一个线索,表明您返回的是一个闭包,而不是预期的任何内容。
请注意,在 Swift 中,有 2 个与闭包定义的变量相关的类似构造:计算属性和惰性变量。
计算属性声明为
var computed: type { closure_returning_result }
计算属性中没有等号。每次您从计算属性中请求一个值时,闭包代码都会运行,并且闭包的返回值是该属性的新值。
惰性变量看起来像这样:
lazy var lazy: type = expression_returning_result
表达式通常是一个闭包,但并非必须如此。惰性 var 的常见形式将使用闭包,如下所示:
lazy var lazy: type = { closure_returning_result }()
惰性变量的声明中有一个等号。如果使用闭包给lazy var赋值,则需要在闭包后面添加括号,这样lazy var被分配的是闭包的返回值,而不是闭包本身。当 @jameel 忘记了他的代码中的右括号时,这个线程就出现了。
考虑以下代码:
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)")
打印输出:
lazy = 2
lazy = 2
lazy = 2
computed = 3
computed = 4
computed = 5
请注意,lazy var 的值不会改变,但计算属性的值会改变。这是它们之间的主要区别。
惰性变量在您第一次请求它时就会被评估,并且该值“粘住”。提供该值的表达式/闭包在您请求之前不会运行,并且仅运行一次。
相比之下,计算属性始终使用闭包,每次请求计算属性的值时,都会执行闭包。
另请注意,惰性变量在您首次引用之前不会被初始化,这一事实可能会产生后果。
如果你颠倒了上面测试代码的顺序:
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)")
输出将是
computed = 2
computed = 3
computed = 4
lazy = 5
lazy = 5
lazy = 5
computed = 6
lazy = 5
computed = 7
使用该示例代码,在调用计算属性 3 次之前,我们不会引用
lazy
。一旦我们引用 lazy
,它就会递增 counter
并将该结果永远保存为新值。
如果我们再次引用
computed
,它会再次增加计数器。
在代码执行的生命周期内,lazy
的值固定在 5。
看起来像是语法问题,请尝试
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
}
您应该在计算属性末尾添加括号才能执行它。
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
}()