【问题标题】:Constraints programmatically with Objective C使用 Objective C 以编程方式约束
【发布时间】:2019-01-30 01:28:24
【问题描述】:

我不知道自己做错了什么:我正在创建一个占据所有屏幕的 UIView(它已经有约束),然后以编程方式创建一个 UI 图像视图:

_panel = [[UIImageView alloc] initWithImage:[self loadImageForKey:@"registerPanel"]];
_panel.frame = CGRectMake(0, 0, 100, 100);
_panel.exclusiveTouch = YES;
_panel.userInteractionEnabled = YES,
[self.scrollView addSubview:_panel];

问题来了:我正在向我创建的面板添加约束,但它崩溃了(我在 ViewWillAppear 上执行此操作):

NSLayoutConstraint *centreHorizontallyConstraint = [NSLayoutConstraint
                                                    constraintWithItem:_panel
                                                    attribute:NSLayoutAttributeCenterX
                                                    relatedBy:NSLayoutRelationEqual
                                                    toItem:self.view
                                                    attribute:NSLayoutAttributeCenterX
                                                    multiplier:1.0
                                                    constant:0];

NSLayoutConstraint *centreVerticalConstraint = [NSLayoutConstraint
                                                constraintWithItem:_panel
                                                attribute:NSLayoutAttributeCenterX
                                                relatedBy:NSLayoutRelationEqual
                                                toItem:self.view
                                                attribute:NSLayoutAttributeCenterX
                                                multiplier:1.0
                                                constant:0];


[_panel addConstraint:centreHorizontallyConstraint];
[_panel addConstraint:centreVerticalConstraint];

错误信息: 添加到视图时,约束的项必须是该视图(或视图本身)的后代。如果在组装视图层次结构之前需要解决约束,这将崩溃。中断 -[UIView _viewHierarchyUnpreparedForConstraint:] 进行调试。

【问题讨论】:

  • " 但它崩溃了" 那么当它崩溃时控制台中是否有任何错误消息?究竟是哪一行导致了崩溃?
  • 你添加你的scrollView作为self.view的子视图了吗?
  • 是的,我做到了。 [self.view addSubview:self.scrollView];
  • 在哪里 [_panel setTranslatesAutoresizingMaskIntoConstraints: NO];
  • " 添加到视图时,约束项必须是该视图(或视图本身)的后代" 在此之前检查 _panel.superview == self.view, _panel.superview.superview == self.view` (根据您的代码),或 _panel.superview....superview == self.view` 似乎并非如此。

标签: ios objective-c autolayout constraints


【解决方案1】:

首先你不能在 panel 和 self.view 之间创建约束,因为没有共同的 parent ,而是你想用滚动视图创建它们

NSLayoutConstraint *centreHorizontallyConstraint = [NSLayoutConstraint
                                                    constraintWithItem:_panel
                                                    attribute:NSLayoutAttributeCenterX
                                                    relatedBy:NSLayoutRelationEqual
                                                    toItem:self.scrollView 
                                                    attribute:NSLayoutAttributeCenterX
                                                    multiplier:1.0
                                                    constant:0];

NSLayoutConstraint *centreVerticalConstraint = [NSLayoutConstraint
                                                constraintWithItem:_panel
                                                attribute:NSLayoutAttributeCenterY
                                                relatedBy:NSLayoutRelationEqual
                                                toItem:self.scrollView 
                                                attribute:NSLayoutAttributeCenterY
                                                multiplier:1.0
                                                constant:0];


[_scrollView  addConstraint:centreHorizontallyConstraint];
[_scrollView  addConstraint:centreVerticalConstraint];

另外两个约束都是 centerX ,您还需要 width 和 height ,或者更好的 top 、leading 、 trailing 和 bottom 到 scrollView ,、宽度和高度是静态的或与self.view成比例的@

//

对于任何想要以编程方式添加约束的视图,您必须设置

[self.scrollView setTranslatesAutoresizingMaskIntoConstraints: NO];
[self.panel setTranslatesAutoresizingMaskIntoConstraints: NO];

【讨论】:

  • 当我尝试设置约束时再次崩溃:'无法在视图上安装约束。约束是否引用了视图子树之外的内容?那是违法的。约束:<0x7ff484796aa0 uiimageview:0x7ff482f871d0.centerx="=" uiscrollview:0x7ff484798d60.centerx><0x7ff482f871d0>
  • <b></b>
【解决方案2】:

可以将滚动视图的子视图约束到滚动视图的父视图(本例中为 self.view),但这可能不是您想要的。

编辑:为了澄清,您收到错误的原因是因为您初始化了约束:

toItem:self.view

然后你尝试添加它们:

[_panel addConstraint:centreHorizontallyConstraint];
[_panel addConstraint:centreVerticalConstraint];

您想将它们添加到toItem 对象中:

[self.view addConstraint:centreHorizontallyConstraint];
[self.view addConstraint:centreVerticalConstraint];

同样,您可能不想在主视图中居中 _panel,但这会编译并运行:

#import "AddPanelScrollViewController.h"   /// just default .h

@interface AddPanelScrollViewController ()

@property (strong, nonatomic) UIScrollView *scrollView;
@property (strong, nonatomic) UIImageView *panel;

@end

@implementation AddPanelScrollViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    _scrollView = [UIScrollView new];
    _scrollView.translatesAutoresizingMaskIntoConstraints = NO;

    [self.view addSubview:_scrollView];

    [_scrollView.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:20.0].active = YES;
    [_scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor constant:-20.0].active = YES;
    [_scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:20.0].active = YES;
    [_scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-20.0].active = YES;

    _scrollView.backgroundColor = [UIColor blueColor];

    _panel = [UIImageView new];

    // required
    _panel.translatesAutoresizingMaskIntoConstraints = NO;

    [self.scrollView addSubview:_panel];

    // frame will be ignored when using auto-layout / constraints
//  _panel.frame = CGRectMake(0, 0, 100, 100);

    _panel.exclusiveTouch = YES;
    _panel.userInteractionEnabled = YES;
    _panel.backgroundColor = [UIColor redColor];

    // _panel needs width and height constraints
    [_panel.widthAnchor constraintEqualToConstant:100.0].active = YES;
    [_panel.heightAnchor constraintEqualToConstant:100.0].active = YES;

    NSLayoutConstraint *centreHorizontallyConstraint = [NSLayoutConstraint
                                                        constraintWithItem:_panel
                                                        attribute:NSLayoutAttributeCenterX
                                                        relatedBy:NSLayoutRelationEqual
                                                        toItem:self.view
                                                        attribute:NSLayoutAttributeCenterX
                                                        multiplier:1.0
                                                        constant:0];

    NSLayoutConstraint *centreVerticalConstraint = [NSLayoutConstraint
                                                    constraintWithItem:_panel
                                                    attribute:NSLayoutAttributeCenterY
                                                    relatedBy:NSLayoutRelationEqual
                                                    toItem:self.view
                                                    attribute:NSLayoutAttributeCenterY
                                                    multiplier:1.0
                                                    constant:0];

    // if constraints are releated to "self.view" that's where they need to be added
    [self.view addConstraint:centreHorizontallyConstraint];
    [self.view addConstraint:centreVerticalConstraint];

}

【讨论】:

    猜你喜欢
    • 2015-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多