【问题标题】:ios 11 - UIButton inside UIBarButtonItem causes an autolayout errorios 11 - UIBarButtonItem 内的 UIButton 导致自动布局错误
【发布时间】:2017-11-23 22:09:15
【问题描述】:

我有一个将 UIButton 添加到 UIBarButtonItem 的已知问题。我尝试按照stackoveflow 中的建议添加自动布局约束,但出现如下错误。

UIButton *sortButton = [UIButton buttonWithType:UIButtonTypeCustom];
[sortButton setFrame:CGRectMake(10, 0, 100, 30)];
[sortButton setTitle:@"Sort" forState:UIControlStateNormal];
[[sortButton titleLabel] setFont:[UIFont boldSystemFontOfSize:13]];
[sortButton setBackgroundImage:[UIImage imageNamed:@"backgroun-button.png"] forState:UIControlStateNormal];
[sortButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[sortButton addTarget:self action:@selector(sortCollection:) forControlEvents:UIControlEventTouchUpInside];
[sortButton applyNavBarConstraints:100 height:30];

[self setSortCollection:item];

[self setToolbarItems:[NSArray arrayWithObjects:self.sortCollection, nil]];

自动布局约束:

- (void)applyNavBarConstraints:(CGFloat)width height:(CGFloat)height
{
    if (width == 0 || height == 0) {
        return;
    }

    NSLayoutConstraint* w = [self.widthAnchor constraintEqualToConstant:width];
    NSLayoutConstraint * h = [self.heightAnchor constraintEqualToConstant:height];

    [w setActive:YES];
    [h setActive:YES];
}

堆栈跟踪:

[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:0x608000280af0 h=--& v=--& UIToolbar:0x7f85ca1327e0.width == 768   (active)>",
    "<NSLayoutConstraint:0x6000002826c0 _UIToolbarContentView:0x7f85ca1307b0.trailing == UIToolbar:0x7f85ca1327e0.trailing   (active)>",
    "<NSLayoutConstraint:0x600000282580 H:|-(0)-[_UIToolbarContentView:0x7f85ca1307b0]   (active, names: '|':UIToolbar:0x7f85ca1327e0 )>",
    "<NSLayoutConstraint:0x600000285410 H:|-(0)-[_UIButtonBarStackView:0x7f85ca135660]   (active, names: '|':_UIToolbarContentView:0x7f85ca1307b0 )>",
    "<NSLayoutConstraint:0x600000285460 _UIButtonBarStackView:0x7f85ca135660.trailing == _UIToolbarContentView:0x7f85ca1307b0.trailing   (active)>",
    "<NSLayoutConstraint:0x600000285500 UIButton:0x7f85ca131b90'Sortieren'.width == 100   (active)>",
    "<NSLayoutConstraint:0x608000280ff0 'UISV-canvas-connection' UILayoutGuide:0x6000001ba240'UIViewLayoutMarginsGuide'.leading == UIButton:0x7f85ca131b90'Sortieren'.leading   (active)>",
    "<NSLayoutConstraint:0x608000280d70 'UISV-canvas-connection' UILayoutGuide:0x6000001ba240'UIViewLayoutMarginsGuide'.trailing == UIButton:0x7f85ca131b90'Sortieren'.trailing   (active)>",
    "<NSLayoutConstraint:0x600000284f10 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x6000001ba240'UIViewLayoutMarginsGuide'](LTR)   (active, names: '|':_UIButtonBarStackView:0x7f85ca135660 )>",
    "<NSLayoutConstraint:0x600000285190 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x6000001ba240'UIViewLayoutMarginsGuide']-(0)-|(LTR)   (active, names: '|':_UIButtonBarStackView:0x7f85ca135660 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600000285500 UIButton:0x7f85ca131b90'Sortieren'.width == 100   (active)>

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.

【问题讨论】:

  • 我一般用这个没有任何约束,加上灵活的空格UIBarButtonSystemItemFlexibleSpace为什么需要约束?
  • iOS11 现在为 UIBatButtonItem 使用自动布局,即它还为您的 Sortieren 按钮设置前导和尾随约束。因此,不再像您那样设置宽度约束。尝试不设置此约束,冲突应该消失。
  • @ReinhardMänner 我需要为我的按钮设置宽度,否则我的按钮太长了,这是我们无法预料的。

标签: ios objective-c ios-autolayout


【解决方案1】:

条形按钮被限制在左右,因此必须打破宽度限制。您可以通过向工具栏添加灵活空间来解决此问题。这允许您限制按钮的宽度,并让灵活的空间填充其余部分。

对象 C:

UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[self setToolbarItems:[NSArray arrayWithObjects:self.sortCollection, flexItem, nil]];

斯威夫特:

let flexItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
toolbar.setItems([barButtonItem, flexItem], animated: false)

【讨论】:

    【解决方案2】:

    自 iOS11 以来我也遇到过这个问题。我通过使用它自己的 XIB 创建一个自定义视图并在其中放置一个按钮来解决它。然后,您可以轻松地在 XIB 的 InterfaceBuilder 中设置约束。 那么当你真正想在barbuttonitem中使用它时,代码就很短了:

    self.customButtonView = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([CustomButtonView class]) owner:nil options:nil] objectAtIndex:0];
    [self.customButtonView.button addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.customButtonView];
    

    只是不要忘记第二行,您实际上必须为按钮分配一个选择器(当然这是自定义视图中的一个 IBOutlet)。

    【讨论】:

      【解决方案3】:

      使用这种简单的方法来创建具有自动布局的按钮。根据 UIView 的大小,创建按钮将具有灵活的宽度。无需添加额外的约束。

      UIButton *sortButton = [UIButton buttonWithType:UIButtonTypeCustom];
          [sortButton setFrame:CGRectMake(10, 0, self.view.frame.size.width - 10, 30)];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多