有没有办法在类似于swift中安卓TextView.setError()
的UITextField
上显示验证错误?
发布于 2015-06-01 21:28:18
UITextField
没有提供开箱即用的验证功能。您可以找到一些开源API来帮助您完成此任务。一种可能的选择是研究SSValidationTextField应用编程接口。
代码应该是
var phoneValidationTextField = SSValidationTextField(frame: CGRectMake(200, 200, 150, 50))
phoneValidationTextField.validityFunction = self.isValidPhone
phoneValidationTextField.delaytime = 0.5
phoneValidationTextField.errorText = "Incorrect Format"
phoneValidationTextField.successText = "Valid Format"
phoneValidationTextField.borderStyle = UITextBorderStyle.RoundedRect
self.addSubview(phoneValidationTextField)
发布于 2015-06-01 21:20:45
您可以通过将UITextField
委托设置为视图控制器来验证文本,然后执行以下操作:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Your method to validate the input
// self.validateInputText()
return true
}
如果你愿意,你甚至可以改变它的边框颜色:
textField.layer.borderColor = UIColor.redColor().CGColor
我希望这对你有帮助。
发布于 2019-06-25 03:02:31
经过一天的工作,我在Swift上模拟了TextView.setError()
。下面是我得到的信息:
swift 5上的代码:
import UIKit
private var rightViews = NSMapTable<UITextField, UIView>(keyOptions: NSPointerFunctions.Options.weakMemory, valueOptions: NSPointerFunctions.Options.strongMemory)
private var errorViews = NSMapTable<UITextField, UIView>(keyOptions: NSPointerFunctions.Options.weakMemory, valueOptions: NSPointerFunctions.Options.strongMemory)
extension UITextField {
// Add/remove error message
func setError(_ string: String? = nil, show: Bool = true) {
if let rightView = rightView, rightView.tag != 999 {
rightViews.setObject(rightView, forKey: self)
}
// Remove message
guard string != nil else {
if let rightView = rightViews.object(forKey: self) {
self.rightView = rightView
rightViews.removeObject(forKey: self)
} else {
self.rightView = nil
}
if let errorView = errorViews.object(forKey: self) {
errorView.isHidden = true
errorViews.removeObject(forKey: self)
}
return
}
// Create container
let container = UIView()
container.translatesAutoresizingMaskIntoConstraints = false
// Create triangle
let triagle = TriangleTop()
triagle.backgroundColor = .clear
triagle.translatesAutoresizingMaskIntoConstraints = false
container.addSubview(triagle)
// Create red line
let line = UIView()
line.backgroundColor = .red
line.translatesAutoresizingMaskIntoConstraints = false
container.addSubview(line)
// Create message
let label = UILabel()
label.text = string
label.textColor = .white
label.numberOfLines = 0
label.font = UIFont.systemFont(ofSize: 15)
label.backgroundColor = .black
label.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 250), for: .horizontal)
label.translatesAutoresizingMaskIntoConstraints = false
container.addSubview(label)
// Set constraints for triangle
triagle.heightAnchor.constraint(equalToConstant: 10).isActive = true
triagle.widthAnchor.constraint(equalToConstant: 15).isActive = true
triagle.topAnchor.constraint(equalTo: container.topAnchor, constant: -10).isActive = true
triagle.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -15).isActive = true
// Set constraints for line
line.heightAnchor.constraint(equalToConstant: 3).isActive = true
line.topAnchor.constraint(equalTo: triagle.bottomAnchor, constant: 0).isActive = true
line.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true
line.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: 0).isActive = true
// Set constraints for label
label.topAnchor.constraint(equalTo: line.bottomAnchor, constant: 0).isActive = true
label.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: 0).isActive = true
label.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true
label.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: 0).isActive = true
if !show {
container.isHidden = true
}
// superview!.superview!.addSubview(container)
UIApplication.shared.keyWindow!.addSubview(container)
// Set constraints for container
container.widthAnchor.constraint(lessThanOrEqualTo: superview!.widthAnchor, multiplier: 1).isActive = true
container.trailingAnchor.constraint(equalTo: superview!.trailingAnchor, constant: 0).isActive = true
container.topAnchor.constraint(equalTo: superview!.bottomAnchor, constant: 0).isActive = true
// Hide other error messages
let enumerator = errorViews.objectEnumerator()
while let view = enumerator!.nextObject() as! UIView? {
view.isHidden = true
}
// Add right button to textField
let errorButton = UIButton(type: .custom)
errorButton.tag = 999
errorButton.setImage(UIImage(named: "ic_error"), for: .normal)
errorButton.frame = CGRect(x: 0, y: 0, width: frame.size.height, height: frame.size.height)
errorButton.addTarget(self, action: #selector(errorAction), for: .touchUpInside)
rightView = errorButton
rightViewMode = .always
// Save view with error message
errorViews.setObject(container, forKey: self)
}
// Show error message
@IBAction
func errorAction(_ sender: Any) {
let errorButton = sender as! UIButton
let textField = errorButton.superview as! UITextField
let errorView = errorViews.object(forKey: textField)
if let errorView = errorView {
errorView.isHidden.toggle()
}
let enumerator = errorViews.objectEnumerator()
while let view = enumerator!.nextObject() as! UIView? {
if view != errorView {
view.isHidden = true
}
}
// Don't hide keyboard after click by icon
UIViewController.isCatchTappedAround = false
}
}
class TriangleTop: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else {
return
}
context.beginPath()
context.move(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY))
context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
context.addLine(to: CGPoint(x: (rect.minX / 2.0), y: rect.maxY))
context.closePath()
context.setFillColor(UIColor.red.cgColor)
context.fillPath()
}
}
使用方法:
class MyViewController: UIViewController {
@IBOutlet weak var emailField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
emailField.delegate = self
}
}
// Validation textFields
extension MyViewController: UITextFieldDelegate {
// Remove error message after start editing
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
textField.setError()
return true
}
// Check error
func textFieldDidBeginEditing(_ textField: UITextField) {
Validator.isValidEmail(field: textField)
}
// Check error
func textFieldDidEndEditing(_ textField: UITextField) {
Validator.isValidEmail(field: textField, show: false)
}
}
class Validator {
static let EMAIL_ADDRESS =
"[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
"\\@" +
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" +
"(" +
"\\." +
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" +
")+"
// Validator e-mail from string
static func isValidEmail(_ value: String) -> Bool {
let string = value.trimmingCharacters(in: .whitespacesAndNewlines)
let predicate = NSPredicate(format: "SELF MATCHES %@", Validator.EMAIL_ADDRESS)
return predicate.evaluate(with: string) || string.isEmpty
}
static func isValidEmail(field: UITextField, show: Bool = true) -> Bool {
if Validator.isValidEmail(field.text!) {
field.setError()
return true
} else {
field.setError("Error message", show: show)
}
return false
}
}
https://stackoverflow.com/questions/30574484
复制相似问题