144 lines
5.5 KiB
Swift
144 lines
5.5 KiB
Swift
//
|
|
// TextFieldErrorView.swift
|
|
// WOKA
|
|
//
|
|
// Created by MacBook Pro on 29/04/24.
|
|
//
|
|
|
|
import UIKit
|
|
|
|
//private var rightViews = NSMapTable<UITextField, UIView>(keyOptions: NSPointerFunctions.Options.weakMemory, valueOptions: NSPointerFunctions.Options.strongMemory)
|
|
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) {
|
|
// Remove message
|
|
guard string != nil else {
|
|
|
|
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: -20).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.heightAnchor.constraint(equalToConstant: 30).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
|
|
}
|
|
|
|
// Add container to superview
|
|
if let rootView = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) {
|
|
rootView.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
|
|
}
|
|
|
|
// 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()
|
|
}
|
|
}
|