问题描述
我想从 ViewController 更改 CustomTextField 类中的“leftIcon”变量。 但是,我在 CustomTextField 类中收到以下错误。
自定义文本字段
class CustomTextField: UITextField,UITextFieldDelegate {
//"person"
private var showPassword: Bool = false
var leftIcon: String = ""
private let leftIconView: UIImageView = {
let icon = UIImage(systemName: leftIcon)
let imageView = UIImageView(image: icon)
imageView.contentMode = .scaleAspectFit
imageView.tintColor = .white
return imageView
}()
}
错误:
Instance member 'leftIcon' cannot be used on type 'CustomTextField'; did you mean to use a value of this type instead?
视图控制器
class ViewController: UIViewController {
var textfield = CustomTextField()
override func viewDidLoad() {
super.viewDidLoad()
self.textfield.leftIcon = "person"
}
}
解决方法
我稍微提炼了问题并重新创建了它,因此您需要重新添加我删除的代码。此代码产生相同的错误:
class CustomTextField {
var leftIcon: String = ""
private let leftIconView: UIImageView = {
let icon = UIImage(systemName: leftIcon) // <--- Error here
let imageView = UIImageView(image: icon)
return imageView
}()
}
并找到问题所在。
问题在于,在调用初始化程序之前,初始化 leftIconView
实际上发生在 static
上下文中,因此您无法引用实例属性。我找到了两个简单的解决方案,第一个是使 leftIconView
成为 lazy var
而不是 let
:
class CustomTextField {
var leftIcon: String = ""
private lazy var leftIconView: UIImageView = {
let icon = UIImage(systemName: leftIcon)
let imageView = UIImageView(image: icon)
return imageView
}()
}
第二种解决方案是在初始化程序中初始化 leftIconView
。
class CustomTextField {
var leftIcon: String = ""
private let leftIconView: UIImageView
override init()
{
let icon = UIImage(systemName: leftIcon)
self.leftIconView = UIImageView(image: icon)
}
}
第二种解决方案可能需要您在添加回继承后还为 UIView
实现一些其他初始化程序,当然您需要在初始化程序的末尾调用 super.init
。
附录
上述解决方案确实修复了编译错误,但实际上使用 CustomTextField
上的属性观察器使图标出现在所需的 leftIcon
中
class CustomTextField: UITextField,UITextFieldDelegate {
//"person"
private var showPassword: Bool = false
var leftIcon: String = ""
{
didSet
{
leftIconView = makeImageView(for: leftIcon)
// leftView is the view that is actually displayed. It's set
// once in the initializer,so now that we're updating
// leftIconView,we have to update leftView as well
leftView = leftIconView
// Maybe also do this
leftView?.setNeedsDisplay()
}
}
private lazy var leftIconView: UIImageView = {
makeImageView(for: leftIcon)
}()
private func makeImageView(for imageName: String) -> UIImageView {
let icon = UIImage(systemName: imageName )
let imageView = UIImageView(image: icon)
imageView.contentMode = .scaleAspectFit
imageView.tintColor = .white
return imageView
}
...
}