【问题标题】:WKWebView constrains issue when keyboard pops up键盘弹出时 WKWebView 约束问题
【发布时间】:2017-11-04 17:44:10
【问题描述】:

WKWebView 中的输入获得焦点时,会弹出约束错误。

代码:

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad();
        let wv = WKWebView(frame: CGRect(x: 100, y: 100, width: 100, height: 100));
        wv.loadHTMLString("<input type='text'/>", baseURL: nil); // it also can be select, it makes no difference
        view.addSubview(wv);
    }
}

错误日志:

2017-11-05 00:26:28.861439+0700 achievator[20048:75393577] [LayoutConstraints] Unable to simultaneously satisfy constraints.    Probably at least one of the constraints in the following list is one you don't want.   Try this:       (1) look at each constraint and try to figure out which you don't expect;       (2) find the code that added the unwanted constraint or constraints and fix it.     (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)  (
    "<NSAutoresizingMaskLayoutConstraint:0x60c0000955e0 h=-&- v=-&- UIToolbar:0x7f8540419570.width ==
_UIInputViewContent:0x7f8540411830.width   (active)>",
    "<NSAutoresizingMaskLayoutConstraint:0x60c000095720 h=--& v=--& _UIInputViewContent:0x7f8540411830.width == 0   (active)>",
    "<NSLayoutConstraint:0x60800009a9a0 H:|-(0)-[_UIButtonBarStackView:0x7f854041b2d0]   (active, names: '|':_UIToolbarContentView:0x7f8540402de0 )>",
    "<NSLayoutConstraint:0x60800009a9f0 _UIButtonBarStackView:0x7f854041b2d0.trailing == _UIToolbarContentView:0x7f8540402de0.trailing + 8   (active)>",
    "<NSLayoutConstraint:0x608000099a00 _UIToolbarContentView:0x7f8540402de0.trailing == UIToolbar:0x7f8540419570.trailing   (active)>",
    "<NSLayoutConstraint:0x608000099aa0 H:|-(0)-[_UIToolbarContentView:0x7f8540402de0]   (active, names: '|':UIToolbar:0x7f8540419570 )>",
    "<NSLayoutConstraint:0x6040000981a0 H:|-(0)-[_UIModernBarButton:0x7f854050ef70]   (active, names: '|':_UIButtonBarButton:0x7f854050e7f0 )>",
    "<NSLayoutConstraint:0x6040000981f0 H:[_UIModernBarButton:0x7f854050ef70]-(>=8)-|   (active, names: '|':_UIButtonBarButton:0x7f854050e7f0 )>",
    "<NSLayoutConstraint:0x6040000999b0 H:|-(8)-[_UIModernBarButton:0x7f8540512450'Done']   (active, names: '|':_UIButtonBarButton:0x7f8540511660 )>",
    "<NSLayoutConstraint:0x604000099a00 H:[_UIModernBarButton:0x7f8540512450'Done']-(0)-|   (active, names: '|':_UIButtonBarButton:0x7f8540511660 )>",
    "<NSLayoutConstraint:0x60c000094690 'UISV-canvas-connection' UILayoutGuide:0x6080001a9a00'UIViewLayoutMarginsGuide'.leading ==
_UIButtonBarButton:0x7f854050e7f0.leading   (active)>",
    "<NSLayoutConstraint:0x60c0000946e0 'UISV-canvas-connection' UILayoutGuide:0x6080001a9a00'UIViewLayoutMarginsGuide'.trailing ==
_UIButtonBarButton:0x7f8540511660.trailing   (active)>",
    "<NSLayoutConstraint:0x60c000094780 'UISV-spacing' H:[_UIButtonBarButton:0x7f854050e7f0]-(0)-[UIView:0x7f854050f4c0]   (active)>",
    "<NSLayoutConstraint:0x60c000094960 'UISV-spacing' H:[UIView:0x7f854050f4c0]-(0)-[_UIButtonBarButton:0x7f854050ea30]   (active)>",
    "<NSLayoutConstraint:0x60c000094a00 'UISV-spacing' H:[_UIButtonBarButton:0x7f854050ea30]-(0)-[UIView:0x7f8540511480]   (active)>",
    "<NSLayoutConstraint:0x60c000094a50 'UISV-spacing' H:[UIView:0x7f8540511480]-(0)-[_UIButtonBarButton:0x7f8540511660]   (active)>",
    "<NSLayoutConstraint:0x60800009a6d0 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x6080001a9a00'UIViewLayoutMarginsGuide'](LTR)  (active, names: '|':_UIButtonBarStackView:0x7f854041b2d0 )>",
    "<NSLayoutConstraint:0x60800009a770 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x6080001a9a00'UIViewLayoutMarginsGuide']-(0)-|(LTR)  (active, names: '|':_UIButtonBarStackView:0x7f854041b2d0 )>" )

Will attempt to recover by breaking constraint  <NSLayoutConstraint:0x6040000981f0 H:[_UIModernBarButton:0x7f854050ef70]-(>=8)-|   (active, names: '|':_UIButtonBarButton:0x7f854050e7f0 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful. 2017-11-05 00:26:28.863156+0700 achievator[20048:75393577] [LayoutConstraints] Unable to simultaneously satisfy constraints.     Probably at least one of the constraints in the following list is one you don't want.   Try this:       (1) look at each constraint and try to figure out which you don't expect;       (2) find the code that added the unwanted constraint or constraints and fix it.     (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)  (
    "<NSAutoresizingMaskLayoutConstraint:0x60c0000955e0 h=-&- v=-&- UIToolbar:0x7f8540419570.width ==
_UIInputViewContent:0x7f8540411830.width   (active)>",
    "<NSAutoresizingMaskLayoutConstraint:0x60c000095720 h=--& v=--& _UIInputViewContent:0x7f8540411830.width == 0   (active)>",
    "<NSLayoutConstraint:0x60800009a9a0 H:|-(0)-[_UIButtonBarStackView:0x7f854041b2d0]   (active, names: '|':_UIToolbarContentView:0x7f8540402de0 )>",
    "<NSLayoutConstraint:0x60800009a9f0 _UIButtonBarStackView:0x7f854041b2d0.trailing == _UIToolbarContentView:0x7f8540402de0.trailing + 8   (active)>",
    "<NSLayoutConstraint:0x608000099a00 _UIToolbarContentView:0x7f8540402de0.trailing == UIToolbar:0x7f8540419570.trailing   (active)>",
    "<NSLayoutConstraint:0x608000099aa0 H:|-(0)-[_UIToolbarContentView:0x7f8540402de0]   (active, names: '|':UIToolbar:0x7f8540419570 )>",
    "<NSLayoutConstraint:0x604000098560 H:|-(>=5)-[_UIModernBarButton:0x7f8540510b40]   (active, names: '|':_UIButtonBarButton:0x7f854050ea30 )>",
    "<NSLayoutConstraint:0x604000098650 H:[_UIModernBarButton:0x7f8540510b40]-(>=5)-|   (active, names: '|':_UIButtonBarButton:0x7f854050ea30 )>",
    "<NSLayoutConstraint:0x6040000999b0 H:|-(8)-[_UIModernBarButton:0x7f8540512450'Done']   (active, names: '|':_UIButtonBarButton:0x7f8540511660 )>",
    "<NSLayoutConstraint:0x604000099a00 H:[_UIModernBarButton:0x7f8540512450'Done']-(0)-|   (active, names: '|':_UIButtonBarButton:0x7f8540511660 )>",
    "<NSLayoutConstraint:0x60c000094690 'UISV-canvas-connection' UILayoutGuide:0x6080001a9a00'UIViewLayoutMarginsGuide'.leading ==
_UIButtonBarButton:0x7f854050e7f0.leading   (active)>",
    "<NSLayoutConstraint:0x60c0000946e0 'UISV-canvas-connection' UILayoutGuide:0x6080001a9a00'UIViewLayoutMarginsGuide'.trailing ==
_UIButtonBarButton:0x7f8540511660.trailing   (active)>",
    "<NSLayoutConstraint:0x60c000094780 'UISV-spacing' H:[_UIButtonBarButton:0x7f854050e7f0]-(0)-[UIView:0x7f854050f4c0]   (active)>",
    "<NSLayoutConstraint:0x60c000094960 'UISV-spacing' H:[UIView:0x7f854050f4c0]-(0)-[_UIButtonBarButton:0x7f854050ea30]   (active)>",
    "<NSLayoutConstraint:0x60c000094a00 'UISV-spacing' H:[_UIButtonBarButton:0x7f854050ea30]-(0)-[UIView:0x7f8540511480]   (active)>",
    "<NSLayoutConstraint:0x60c000094a50 'UISV-spacing' H:[UIView:0x7f8540511480]-(0)-[_UIButtonBarButton:0x7f8540511660]   (active)>",
    "<NSLayoutConstraint:0x60800009a6d0 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x6080001a9a00'UIViewLayoutMarginsGuide'](LTR)  (active, names: '|':_UIButtonBarStackView:0x7f854041b2d0 )>",
    "<NSLayoutConstraint:0x60800009a770 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x6080001a9a00'UIViewLayoutMarginsGuide']-(0)-|(LTR)  (active, names: '|':_UIButtonBarStackView:0x7f854041b2d0 )>" )

Will attempt to recover by breaking constraint  <NSLayoutConstraint:0x604000098650 H:[_UIModernBarButton:0x7f8540510b40]-(>=5)-|   (active, names: '|':_UIButtonBarButton:0x7f854050ea30 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

【问题讨论】:

    标签: ios swift wkwebview


    【解决方案1】:

    我的假设是这是 ios 11 中的一个错误。抱怨是关于键盘按钮栏中的组件,这些组件都使用 os 设置的默认值。我在 ios 9 和 ios 10 上运行了相同的代码并且没有收到错误消息。

    【讨论】:

    • 有什么解决办法吗?这可以以某种方式解决吗?在 iOS 13 beta 5 上获得相同的结果
    • 如果您只想删除底部的空白:NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: nil) { (notification) in self.webView.scrollView.contentOffset.y = 0 } @swalkner 如果偏移量不为 0,您可以在 keyboardWillShowNotification 中获取内容偏移量值并在 @ 中进行相应设置987654323@
    【解决方案2】:

    有同样的问题。我正在运行一个干净的项目,香草设置,一旦 webview 键盘获得焦点,这个问题就会出现。这似乎是一个常见问题,可能只是 iOS 11 中的一个错误。

    另见:

    WKWebView LayoutConstraints issue

    【讨论】:

    • 没办法,还是2022年?...
    【解决方案3】:

    键盘打开时一个或多个约束不兼容。

    尝试为您的 WKWebView 设置约束,而不是手动执行框架。

    private func addWKWebView(){
        let wv = WKWebView()
        view.addSubview(wv);
        wv.translatesAutoresizingMaskIntoConstraints = false
    
    
        wv.widthAnchor.constraint(equalTo:   view.widthAnchor  ).isActive = true
        wv.heightAnchor.constraint(equalTo:  view.heightAnchor ).isActive = true
        wv.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        wv.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    }
    

    或类似的东西:

    private func addWKWebView(){
        let wv = WKWebView()
        view.addSubview(wv);
        wv.translatesAutoresizingMaskIntoConstraints = false
    
    
        wv.widthAnchor.constraint(equalToConstant:  100).isActive = true
        wv.heightAnchor.constraint(equalToConstant: 100).isActive = true
        wv.widthAnchor.constraint(equalToConstant:  100).isActive = true
        wv.heightAnchor.constraint(equalToConstant: 100).isActive = true
    }
    

    你需要使用你的约束来设置你想要的 WkWebView。

    【讨论】:

    • 两个都试过了,都没有用。在这两种情况下,错误仍然会弹出。
    • 那么可能是你的其他限制。为什么不在 Storyboard 中添加 WKWebView,这样你就可以实时看到女巫约束在抱怨。
    • 您也可以尝试为其中 4 个添加低优先级: let width = wv.widthAnchor.constraint(equalToConstant: 100) width.isActive = true width.priority = .defaultLow
    • 这对 iOS 13 没有帮助。
    • 这里也一样。 iOS 14. 仍在等待修复
    【解决方案4】:

    当我需要弹出自定义键盘时,我也遇到了这个问题。 最后,我需要做的就是将 html 输入元素的 eventType: 从 "touchstart" 更改为 "click"

    产地:

        function setUpEvent(elem, eventType, handler) {
            return (elem.attachEvent ? elem.attachEvent("on" + eventType, handler)
                : ((elem.addEventListener) ? elem.addEventListener(eventType, handler, false) : null));
        }
    
        window.onload = function () {
    
            var input_ele = document.getElementById('YOUR_ELE_NAME');
            setUpEvent(input_ele, "touchstart", function (e) {
    
                //showKeyboard();//my personal function to show keyboard
            });
        }
    

    它有效:

        function setUpEvent(elem, eventType, handler) {
            return (elem.attachEvent ? elem.attachEvent("on" + eventType, handler)
                : ((elem.addEventListener) ? elem.addEventListener(eventType, handler, false) : null));
        }
    
        window.onload = function () {
    
            var input_ele = document.getElementById('YOUR_ELE_NAME');
            setUpEvent(input_ele, "click", function (e) {//change here
    
                //showKeyboard();//my personal function to show keyboard
            });
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-03
      • 2018-09-01
      • 1970-01-01
      • 2021-11-24
      • 2012-12-23
      • 2013-08-12
      • 2020-07-09
      相关资源
      最近更新 更多