Показывать ошибку в UITextField SWIFT XCODE

У меня есть следующее расширение

private var rightViews = NSMapTable(keyOptions: NSPointerFunctions.Options.weakMemory, valueOptions: NSPointerFunctions.Options.strongMemory)
private var errorViews = NSMapTable(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)

            self.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)
        }

Которая производит меня

introducir la descripción de la imagen aquí

Который размещает это мне в конце вида, как возможно оценивать

то, что я желаю, состоит в том, чтобы мочь оставлять каждую ошибку внизу каждого ящика envez помещения этого в последнее view

Что эта проблема здесь

 self.addSubview(container)

Поскольку я мог бы изменять этот extesion для того, чтобы я разместился под каждым ящиком envez размещения под view, с уже gracais

5
задан 06.08.2019, 03:23
1 ответ

Было бы лучше, чтобы ты сделал custom class для твоего TextField, но, таким образом, ты servirГЎ, только помни, что, когда ты применишь constraints добавлять padding 15 к top предварительного textfield.

import UIKit
import PlaygroundSupport


extension UITextField {

    func removeError () {
        self.layer.sublayers?.removeAll()
    }

    func setError(_ title : String) {
       setupErrorLayout()
        guard let label = self.subviews.first(where: { [110] is UILabel }) else { return }
        (label as? UILabel)?.text = title
    }

    func setupErrorLayout() {
        setupUnderline()
        setupTriangle()
        setupLabel()
    }

    func setupUnderline() {
        let bottomLine = CALayer()
        bottomLine.frame = CGRect.init(x: 0, y: frame.height + 2, width: frame.width, height: 1)
        bottomLine.backgroundColor = UIColor.red.cgColor
        self.borderStyle = .none
        self.layer.addSublayer(bottomLine)

    }


    func setupTriangle() {
        let bounds = CGRect.init(x: frame.width, y: frame.height + 3, width: 10, height: 10)
        let rad = bounds.size.width / 2
        let aSide = rad * sqrt(rad / 2) / 2
        let bSide = rad / 2
        let bezierPath = UIBezierPath()
        bezierPath.move(to: CGPoint.init(x: 0, y: -rad))
        bezierPath.addLine(to: CGPoint.init(x: aSide, y: bSide))
        bezierPath.addLine(to: CGPoint.init(x: -aSide, y: bSide))
        bezierPath.close()
        let triangle = CAShapeLayer()
        triangle.path = bezierPath.cgPath
        triangle.backgroundColor = UIColor.red.cgColor
        triangle.fillColor = UIColor.red.cgColor
        triangle.frame.origin = CGPoint(x: frame.width - rad, y: frame.height)
        self.layer.addSublayer(triangle)
    }

    func setupLabel() {
        let label = UILabel(frame: CGRect.init(x: 0, y: frame.height + 10, width: frame.width, height: 7))
        label.text = ""
        label.font = UIFont.systemFont(ofSize: 8.0)
        label.textAlignment = .right
        self.addSubview(label)
    }

}

class MyViewController : UIViewController {

    let textField = UITextField(frame: CGRect.init(x: 50, y: 50, width: 300, height: 50))

    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white


        textField.backgroundColor = .lightGray
        textField.text = "Some text to evaluate"



        let set = UIButton(frame: CGRect.init(x: 0, y: 200, width: 100, height: 100))
        set.addTarget(self, action: #selector(setAction(_:)), for: .touchUpInside)
        set.backgroundColor = .green

        let unset = UIButton(frame: CGRect.init(x: 150, y: 200, width: 100, height: 100))
        unset.addTarget(self, action: #selector(unsetAction(_:)), for: .touchUpInside)
        unset.backgroundColor = .red

        view.addSubview(textField)
        view.addSubview(set)
        view.addSubview(unset)
        self.view = view
    }

    @objc func setAction(_ sender: Any) {
        textField.setError("Tienes algunos errores")
    }
    @objc func unsetAction(_ sender: Any) {
        textField.removeError()
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
3
ответ дан 01.12.2019, 22:32

Теги

Похожие вопросы