Ios 扩展UITextField以创建可共享组件
我以编程方式添加了许多UITextField组件,它们似乎都有许多共享行 我想将这些代码提取到某种扩展中,这样我就可以共享代码并减少重复行 但我真的很难做到这一点 我已经在下面添加了这些组件的一些示例,希望您能提供一些关于如何实现这一点的信息,请Ios 扩展UITextField以创建可共享组件,ios,swift,uikit,Ios,Swift,Uikit,我以编程方式添加了许多UITextField组件,它们似乎都有许多共享行 我想将这些代码提取到某种扩展中,这样我就可以共享代码并减少重复行 但我真的很难做到这一点 我已经在下面添加了这些组件的一些示例,希望您能提供一些关于如何实现这一点的信息,请 let usernameTextField: UITextField = { let tf = UITextField() tf.placeholder = "Username" tf.backgroundColor = UIC
let usernameTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Username"
tf.backgroundColor = UIColor(white: 0, alpha: 0.03)
tf.font = UIFont.systemFont(ofSize: 14)
tf.borderStyle = .roundedRect
tf.autocorrectionType = .no
tf.autocapitalizationType = .none
tf.spellCheckingType = .no
tf.addTarget(self, action: #selector(handleTextInputChange), for: .editingChanged)
tf.addTarget(nil, action:Selector(("firstResponderAction:")), for:.editingDidEndOnExit)
return tf
}()
let passwordTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Password"
tf.backgroundColor = UIColor(white: 0, alpha: 0.03)
tf.font = UIFont.systemFont(ofSize: 14)
tf.borderStyle = .roundedRect
tf.autocorrectionType = .no
tf.autocapitalizationType = .none
tf.spellCheckingType = .no
tf.returnKeyType = .done
tf.isSecureTextEntry = true
tf.addTarget(self, action: #selector(handleTextInputChange), for: .editingChanged)
tf.addTarget(nil, action:Selector(("firstResponderAction:")), for:.editingDidEndOnExit)
return tf
}()
最简单的解决方案是将
UITextField
子类化,并将共享行包含在重写的init
方法中。然后,您将创建子类的实例,而不是直接创建UITextField
例如:
class MyTextField: UITextField {
override init() {
super.init()
self.backgroundColor = UIColor(white: 0, alpha: 0.03)
self.font = UIFont.systemFont(ofSize: 14)
self.borderStyle = .roundedRect
self.autocorrectionType = .no
self.autocapitalizationType = .none
tfselfspellCheckingType = .no
}
}
let passwordTextField = MyTextField()
...
这里没有“可共享组件”问题。唯一难看的是你的代码并不枯燥(“不要重复你自己”)。所以,让它干燥!只需将常见的重复代码分解成一个可以从所有文本字段创建代码调用的函数。例如,假设您正在viewDidLoad
中执行所有这些操作。然后,您显示的代码可以按如下方式分解:
override func viewDidLoad() {
super.viewDidLoad()
func makeTextField() -> UITextField {
let tf = UITextField()
tf.backgroundColor = UIColor(white: 0, alpha: 0.03)
tf.font = UIFont.systemFont(ofSize: 14)
tf.borderStyle = .roundedRect
tf.autocorrectionType = .no
tf.autocapitalizationType = .none
tf.spellCheckingType = .no
tf.addTarget(self, action: #selector(handleTextInputChange), for: .editingChanged)
tf.addTarget(nil, action:Selector(("firstResponderAction:")), for:.editingDidEndOnExit)
return tf
}
let usernameTextField: UITextField = {
let tf = makeTextField()
tf.placeholder = "Username"
return tf
}()
let passwordTextField: UITextField = {
let tf = makeTextField()
tf.placeholder = "Password"
tf.returnKeyType = .done
tf.isSecureTextEntry = true
return tf
}()
// ... do something with text fields here ...
}
这里有另一种方法。使用扩展来设置公共属性,如
extension UITextField{
func initCommonProperties(withPlaceholder placeholder:String){
backgroundColor = UIColor(white: 0, alpha: 0.03)
font = UIFont.systemFont(ofSize: 14)
borderStyle = .roundedRect
autocorrectionType = .no
autocapitalizationType = .none
spellCheckingType = .no
addTarget(self, action: #selector(handleTextInputChange), for: .editingChanged)
addTarget(nil, action:Selector(("firstResponderAction:")), for:.editingDidEndOnExit)
self.placeholder = placeholder
}
}
let usernameTextField: UITextField = {
let tf = UITextField()
tf.initCommonProperties(withPlaceholder:"Username")
return tf
}()
let passwordTextField: UITextField = {
let tf = UITextField()
tf.initCommonProperties(withPlaceholder:"Password")
return tf
}()
extension UITextField{
convenience init(withPlaceholder placeholder:String){
self.init()
backgroundColor = UIColor(white: 0, alpha: 0.03)
font = UIFont.systemFont(ofSize: 14)
borderStyle = .roundedRect
autocorrectionType = .no
autocapitalizationType = .none
spellCheckingType = .no
addTarget(self, action: #selector(handleTextInputChange), for: .editingChanged)
addTarget(nil, action:Selector(("firstResponderAction:")), for:.editingDidEndOnExit)
self.placeholder = placeholder
}
}
let usernameTextField = UITextField(withPlaceholder:"Username")
let passwordTextField = UITextField(withPlaceholder:"Password")
您也可以使用函数而不是扩展来执行相同的操作
class MyTextFieldUtils{
static func initCommonProperties(tf:UITextField){
tf.backgroundColor = UIColor(white: 0, alpha: 0.03)
tf.font = UIFont.systemFont(ofSize: 14)
tf.borderStyle = .roundedRect
tf.autocorrectionType = .no
tf.autocapitalizationType = .none
tf.spellCheckingType = .no
tf.addTarget(self, action: #selector(handleTextInputChange), for: .editingChanged)
tf.addTarget(nil, action:Selector(("firstResponderAction:")), for:.editingDidEndOnExit)
}
}
let usernameTextField: UITextField = {
let tf = UITextField()
MyTextFieldUtils.initCommonProperties(tf)
tf.placeholder = "Username"
return tf
}()
let passwordTextField: UITextField = {
let tf = UITextField()
MyTextFieldUtils.initCommonProperties(tf)
tf.placeholder = "Password"
return tf
}()
前者的优点是API简单得多。缺点是现在所有UITextFields都将获得initCommonProperties
函数
后者的优点是它完全分离了关注点,但代价是更加冗长。但是,您可以通过创建多个函数或多个类来为不同类型的文本框(或任何控件)创建不同的初始值设定项,每个函数或类都具有相同的函数
另一种方法是通过扩展创建方便的初始值设定项,如
extension UITextField{
func initCommonProperties(withPlaceholder placeholder:String){
backgroundColor = UIColor(white: 0, alpha: 0.03)
font = UIFont.systemFont(ofSize: 14)
borderStyle = .roundedRect
autocorrectionType = .no
autocapitalizationType = .none
spellCheckingType = .no
addTarget(self, action: #selector(handleTextInputChange), for: .editingChanged)
addTarget(nil, action:Selector(("firstResponderAction:")), for:.editingDidEndOnExit)
self.placeholder = placeholder
}
}
let usernameTextField: UITextField = {
let tf = UITextField()
tf.initCommonProperties(withPlaceholder:"Username")
return tf
}()
let passwordTextField: UITextField = {
let tf = UITextField()
tf.initCommonProperties(withPlaceholder:"Password")
return tf
}()
extension UITextField{
convenience init(withPlaceholder placeholder:String){
self.init()
backgroundColor = UIColor(white: 0, alpha: 0.03)
font = UIFont.systemFont(ofSize: 14)
borderStyle = .roundedRect
autocorrectionType = .no
autocapitalizationType = .none
spellCheckingType = .no
addTarget(self, action: #selector(handleTextInputChange), for: .editingChanged)
addTarget(nil, action:Selector(("firstResponderAction:")), for:.editingDidEndOnExit)
self.placeholder = placeholder
}
}
let usernameTextField = UITextField(withPlaceholder:"Username")
let passwordTextField = UITextField(withPlaceholder:"Password")
希望这有帮助 请注意,如果这些是实例属性,那么您的代码是非法的。在初始化
self
的实例属性时,不能谈论self
(就像在addTarget
调用中一样)。只是一个友好的注释。当你提到像“干燥”这样的东西时,你应该把第一个引用作为一个链接,这样其他人就可以深入了解它的含义。同意@LeoDabus。这看起来是剪切复制粘贴错误,因为您在直接设置属性时引用的是“tf”。@LeoDabus Good spot,是的,我在这里复制粘贴了OPs代码,将进行更改并记下以备将来检查。