【问题标题】:inputAccessoryView, API error? _UIKBCompatInputView? UIViewNoIntrinsicMetric, simple code, can't figure outinputAccessoryView,API 错误? _UIKBCompatInputView? UIViewNoIntrinsicMetric,简单的代码,想不通
【发布时间】:2021-10-16 17:53:45
【问题描述】:

用以下两种方式之一帮助我:

  1. 如何解决问题?或
  2. 如何理解错误信息?

项目总结

所以我通过制作一个只有一个UIButton 的小项目来了解inputAccessoryView。点击该按钮会调用带有inputAccessoryView 的键盘,其中包含1 个UITextField 和1 个UIButtoninputAccessoryView 中的 UITextField 将是最后一个 firstResponder,它负责与 inputAccessoryView 一起使用的键盘

错误信息

API error: <_UIKBCompatInputView: 0x7fcefb418290; frame = (0 0; 0 0); layer = <CALayer: 0x60000295a5e0>> returned 0 width, assuming UIViewNoIntrinsicMetric

代码

如下所示非常简单

  1. 自定义UIView 用作inputAccessoryView。它安装了 2 个 UI 插座,并告诉响应者链它 canBecomeFirstResponder
class CustomTextFieldView: UIView {

    let doneButton:UIButton = {
        let button = UIButton(type: .close)
        return button
    }()
    
    let textField:UITextField = {
        let textField = UITextField()
        textField.placeholder = "placeholder"
        return textField
    }()
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        initSetup()
    }
    
    override init(frame:CGRect) {
        super.init(frame: frame)
        initSetup()
    }
    
    convenience init() {
        self.init(frame: .zero)
    }
    
    func initSetup() {
        addSubview(doneButton)
        addSubview(textField)
    }
    
    func autosizing(to vc: UIViewController) {
        frame = CGRect(x: 0, y: 0, width: vc.view.frame.size.width, height: 40)
        let totalWidth = frame.size.width - 40
        doneButton.frame = CGRect(x: totalWidth * 4 / 5 + 20,
                                  y: 0,
                                  width: totalWidth / 5,
                                  height: frame.size.height)
        textField.frame = CGRect(x: 20,
                                 y: 0,
                                 width: totalWidth * 4 / 5,
                                 height: frame.size.height)
    }
    
    override var canBecomeFirstResponder: Bool { true }
    
    override var intrinsicContentSize: CGSize {
        CGSize(width: 400, height: 40)
    } // overriding this variable seems to have no effect.
}
  1. 主VC使用自定义UIView作为inputAccessoryView。 inputAccessoryView 中的UITextField 最终会变成真正的firstResponder,我相信。
class ViewController: UIViewController {
    
    let customView = CustomTextFieldView()
    var keyboardShown = false
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        customView.autosizing(to: self)
        
    
    }
    
    @IBAction func summonKeyboard() {
        print("hello")
        keyboardShown = true
        self.becomeFirstResponder()
        customView.textField.becomeFirstResponder()
    }

    override var canBecomeFirstResponder: Bool { keyboardShown }
    
    override var inputAccessoryView: UIView? {
        return customView
    }
}
  1. 我在互联网上看到有人说如果我在实体手机上运行,​​此错误消息就会消失。当我尝试时,我并没有离开。
  2. 我覆盖了自定义视图的intrinsicContentSize,但是没有效果。
  3. 当我点击summon时,错误消息同时显示两次。
  4. 错误消息指的是什么“框架”或“层”?它是指自定义视图的框架和层吗?

【问题讨论】:

    标签: ios uiview autolayout uitextfield inputaccessoryview


    【解决方案1】:

    如果我们使用Debug View Hierarchy,我们可以看到_UIKBCompatInputView 是键盘(内部)视图层次结构的一部分。

    在内部视图中看到约束错误/警告并不罕见。

    由于框架和/或内在内容大小似乎没有任何影响,我认为这是无法避免的(似乎也需要避免)。

    附带说明,您可以使用自动布局约束来保持“完成”按钮的圆形。这是一个例子:

    class CustomTextFieldView: UIView {
        
        let textField: UITextField = {
            let tf = UITextField()
            tf.font = .systemFont(ofSize: 16)
            tf.autocorrectionType = .no
            tf.returnKeyType = .done
            tf.placeholder = "placeholder"
            // textField backgroundColor so we can see its frame
            tf.backgroundColor = .yellow
            return tf
        }()
        
        let doneButton:UIButton = {
            let button = UIButton(type: .close)
            return button
        }()
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            commonInit()
        }
        
        func commonInit() -> Void {
            
            autoresizingMask = [.flexibleHeight, .flexibleWidth]
            
            [doneButton, textField].forEach { v in
                v.translatesAutoresizingMaskIntoConstraints = false
                addSubview(v)
            }
            NSLayoutConstraint.activate([
                
                // constrain doneButton
                //  Trailing: 20-pts from trailing
                doneButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20.0),
                //  Top and Bottom 8-pts from top and bottom
                doneButton.topAnchor.constraint(equalTo: topAnchor, constant: 8.0),
                doneButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8.0),
                //  Width equal to default height
                //  this will keep the button round instead of oval
                doneButton.widthAnchor.constraint(equalTo: doneButton.heightAnchor),
                
                // constrain textField
                //  Leading: 20-pts from leading
                textField.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20.0),
                //  Trailing: 8-pts from doneButton leading
                textField.trailingAnchor.constraint(equalTo: doneButton.leadingAnchor, constant: -8.0),
                //  vertically centered
                textField.centerYAnchor.constraint(equalTo: centerYAnchor),
                
            ])
    
        }
    
    }
    
    class CustomTextFieldViewController: UIViewController {
        
        let customView = CustomTextFieldView()
        
        var keyboardShown = false
        
        override func viewDidLoad() {
            super.viewDidLoad()
        }
        
        @IBAction func summonKeyboard() {
            print("hello")
            keyboardShown = true
            self.becomeFirstResponder()
            customView.textField.becomeFirstResponder()
        }
        
        override var canBecomeFirstResponder: Bool { keyboardShown }
        
        override var inputAccessoryView: UIView? {
            return customView
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-15
      • 2020-04-11
      • 2014-08-16
      • 2011-09-21
      • 2014-04-01
      • 1970-01-01
      • 2017-06-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多