I want to change the 'leftIcon' variable in the CustomTextField class from the ViewController. however, I get the following error in the CustomTextField class.
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
}()
}
Error:
Instance member 'leftIcon' cannot be used on type 'CustomTextField'; did you mean to use a value of this type instead?
ViewController
class ViewController: UIViewController {
var textfield = CustomTextField()
override func viewDidLoad() {
super.viewDidLoad()
self.textfield.leftIcon = "person"
}
}
I distilled the problem down a bit and recreated it, so you'll want to add back the code I removed. This code produces the same error:
class CustomTextField {
var leftIcon: String = ""
private let leftIconView: UIImageView = {
let icon = UIImage(systemName: leftIcon) // <--- Error here
let imageView = UIImageView(image: icon)
return imageView
}()
}
And tracked down the problem.
The problem is that initializing leftIconView
is actually happening in a static
context before the initializer is called, so you can't refer to instance properties. I found two easy solutions, the first is make leftIconView
a lazy var
instead of a let
:
class CustomTextField {
var leftIcon: String = ""
private lazy var leftIconView: UIImageView = {
let icon = UIImage(systemName: leftIcon)
let imageView = UIImageView(image: icon)
return imageView
}()
}
The second solution is to just initialize leftIconView
in the initializer.
class CustomTextField {
var leftIcon: String = ""
private let leftIconView: UIImageView
override init()
{
let icon = UIImage(systemName: leftIcon)
self.leftIconView = UIImageView(image: icon)
}
}
This second solution will probably require that you also implement some other initializers for UIView
once you add back that inheritance, and of course you'll need to call super.init
at the end of the initializer.
The above solution did indeed fix the compile error, but actually making the icon appear in the CustomTextField
required using a property observer on 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
}
...
}