TextField отклонил resignFirstResponder при удалении из иерархии - PullRequest
1 голос
/ 22 мая 2019

Я пытаюсь создать настраиваемое представление текстового поля / кнопки отправки, которое переопределяет inputAccessoryView, но у меня есть 2 проблемы, которые я не могу решить:

Когда пользовательское представление становится первым респондентом, я получаю это предупреждение дважды:

CustomKeyboardProject[5958:3107074] API error: 
<_UIKBCompatInputView: 0x119e2bd70; frame = (0 0; 0 0); 
layer = <CALayer: 0x283df9e00>> returned 0 width, 
assuming UIViewNoIntrinsicMetric

Затем, когда я пытаюсь отказаться от пользовательского представления в качестве первого респондента, XCode выдает это предупреждение:

CustomKeyboardProject[5958:3107074] -[UIWindow
endDisablingInterfaceAutorotationAnimated:] called on <UITextEffectsWindow:
0x11a055400; frame = (0 0; 375 667); opaque = NO; autoresize = W+H; layer =
<UIWindowLayer: 0x283df78a0>> without matching 
-beginDisablingInterfaceAutorotation. Ignoring.

Кто-нибудь смог заставить замолчать эти предупреждения?

Вот мой код:

protocol CustomTextFieldDelegate: class {
    func sendMessage()
}

class CustomTextField: UITextField {

    override var canBecomeFirstResponder: Bool {
        return true
    }

    override var canResignFirstResponder: Bool {
        return true
    }
}

class CustomKeyboardView: UIView {

    let textField: CustomTextField = {
        let textField = CustomTextField()
        textField.backgroundColor = .green
        textField.textColor = .white
        return textField
    }()

    let attachButton: UIButton = {
        let button = UIButton()
        button.backgroundColor = .red
        button.setTitle("Attach", for: .normal)
        return button
    }()

    let sendButton: UIButton = {
        let button = UIButton()
        button.backgroundColor = .blue
        button.setTitle("Send", for: .normal)
        button.addTarget(self, action: #selector(sendMessage), for: .touchUpInside)
        return button
    }()

    @objc func sendMessage() {
        delegate?.sendMessage()
    }

    weak var delegate: CustomTextFieldDelegate?

    init() {
        super.init(frame: .zero)
        isUserInteractionEnabled = true
        setViews()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setViews() {
        let subviews = [attachButton, sendButton, textField]

        subviews.forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
            addSubview($0)
        }

        autoresizingMask = .flexibleHeight

        subviews.forEach {
            NSLayoutConstraint.activate([
                $0.centerYAnchor.constraint(equalTo: centerYAnchor),
                ])
        }

        layoutSubviews()

        [attachButton, sendButton].forEach {
            NSLayoutConstraint.activate([
                $0.widthAnchor.constraint(equalTo: $0.heightAnchor),
                $0.heightAnchor.constraint(equalTo: textField.heightAnchor)
                ])
        }

        NSLayoutConstraint.activate([
            textField.topAnchor.constraint(equalTo: topAnchor),
            attachButton.leftAnchor.constraint(equalTo: leftAnchor),
            textField.leadingAnchor.constraint(equalTo: attachButton.trailingAnchor),
            sendButton.leadingAnchor.constraint(equalTo: textField.trailingAnchor),
            sendButton.trailingAnchor.constraint(equalTo: trailingAnchor),
            ])
    }

    override var intrinsicContentSize: CGSize {
        return .zero
    }
}

class CustomTableView: UITableView {

    let keyboardView = CustomKeyboardView()

    override init(frame: CGRect, style: UITableView.Style) {
        super.init(frame: frame, style: style)
        keyboardDismissMode = .interactive
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override var canBecomeFirstResponder: Bool {
        return true
    }

    override var canResignFirstResponder: Bool {
        return true
    }

    override var inputAccessoryView: UIView? {
        return keyboardView
    }
}

private let reuseId = "MessageCellId"

class ExampleViewController: UITableViewController {

    private let customTableView = CustomTableView()

    var messages = [String]()

    override func loadView() {
        tableView = customTableView
        view = tableView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.becomeFirstResponder()
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: reuseId)
        customTableView.keyboardView.delegate = self
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        DispatchQueue.main.async {
            self.customTableView.keyboardView.textField.becomeFirstResponder()
        }
    }

    // tableView delegate methods

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return messages.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: reuseId)
        cell?.textLabel?.text = messages[indexPath.row]
        return cell!
    }

    override func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        customTableView.keyboardView.textField.resignFirstResponder()
    }
}

extension ExampleViewController: CustomTextFieldDelegate {
    func sendMessage() {
        // double check something is in textField
        let textField = customTableView.keyboardView.textField
        guard let body = textField.text, body != "" else { return }
        messages.append(body)
        tableView.reloadData()

        view.endEditing(true)
        customTableView.keyboardView.textField.text = ""
    }
}
...