以编程方式添加View约束时,在容器层次结构崩溃中找不到视图

时间:2016-07-31 04:04:26

标签: ios objective-c cocoa-touch autolayout nslayoutconstraint

虽然崩溃信息非常清楚,但我检查了我的代码,一切看起来都很好。我唯一担心的是因为我在一个被设置为键盘附件视图的视图上设置约束,这可能是整个视图层次结构设置不正确的原因。

这是我正在做的事情:

步骤1:创建自定义配件视图(0到9之间的数字栏)并将其放在常规键盘上。

MyAccessoryView *anAccessoryView = [[MyAccessoryView alloc] initWithFrame:CGRectMake(0, 0, 320, 46.0f)];
anAccessoryView.delegate = self;
self.textField.inputAccessoryView = anAccessoryView;

第2步:在自定义配件视图(UIView的子视图)中,添加按钮和相关处理。将它们添加到超级视图,然后在延迟1秒后调用方法以添加约束。

- (id)initWithFrame:(CGRect)iFrame {
    if (self = [super initWithFrame:iFrame]) {
        [self refresh];
        self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    }

    [self setExclusiveTouch:YES];
    return self;
}


- (void)refresh {
    if (!self.layoutController) {
        self.layoutController = [[MyAccessoryViewLayoutController alloc] init];
    }

    self.backgroundColor = [self.layoutController colorForNumericInputAccessory:self];
    self.userInteractionEnabled = YES;

    NSMutableArray *buttonsArray = [NSMutableArray arrayWithCapacity:10];

    // Adding number keys to the accessory view and setting thier properties
    for (NSInteger i = 1; i < 11; i++) {
        MyAccessoryViewNumericButton *aKeyboardButton = [MyAccessoryViewNumericButton buttonWithType:UIButtonTypeCustom];
        aKeyboardButton.tag = i;
        aKeyboardButton.frame = CGRectMake(0, 0, 32.0, 44);

        [aKeyboardButton setTitle: [NSString stringWithFormat:@"%ld", (long)i % 10] forState:UIControlStateNormal];
        NSString *aButtonImageTitle = [self.layoutController buttonNormalStateImageNameForIndex:(i % 10) forNumericInputAccessory:self];
        [aKeyboardButton setBackgroundImage:[UIImage imageNamed:aButtonImageTitle] forState:UIControlStateNormal];
        aKeyboardButton.backgroundColor = [UIColor clearColor];
        [aKeyboardButton setTitleColor:[UIColor blackColor] forState: UIControlStateNormal];
        [aKeyboardButton setExclusiveTouch:YES];
        aKeyboardButton.titleLabel.font = [self.layoutController fontForButtonTitlesForNumericInputAccessory:self];


        if (self.layoutController.interfaceIdiom == UIUserInterfaceIdiomPhone) {
            aKeyboardButton.titleLabel.textAlignment = NSTextAlignmentCenter;
        } else {
            NSString *aButtonHighlightedImageTitle = [self.layoutController buttonHighlightedStateImageNameForIndex:(i % 10) forNumericInputAccessory:self];
            [aKeyboardButton setBackgroundImage:[UIImage imageNamed:aButtonHighlightedImageTitle] forState:UIControlStateHighlighted];
        }

        aKeyboardButton.hidden = NO;
        aKeyboardButton.enabled = YES;
        aKeyboardButton.tag = i;
        [aKeyboardButton addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];

        [self addSubview:aKeyboardButton];
        [buttonsArray addObject:aKeyboardButton];

        if (self.layoutController.interfaceIdiom == UIUserInterfaceIdiomPhone) {
            UIImage *aPressedButtonImage = [UIImage imageNamed:[self.layoutController buttonHighlightedStateImageNameForIndex:(i % 10) forNumericInputAccessory:self]];
            CGRect aPressedButtonViewFrame = [self.layoutController frameForPressedButtonViewWithIndex:(i % 10) forNumericInputAccessory:self];
            UIView *aPressedButtonView = [[UIView alloc] initWithFrame:aPressedButtonViewFrame];
            aPressedButtonView.backgroundColor = [UIColor clearColor];
            aPressedButtonView.userInteractionEnabled = YES;
            aPressedButtonView.hidden = YES;

            UIImageView *aPressedButtonImageView = [[UIImageView alloc] initWithImage:aPressedButtonImage];
            aPressedButtonImageView.frame = CGRectMake(0.0, 0.0, aPressedButtonViewFrame.size.width, aPressedButtonViewFrame.size.height);
            aPressedButtonImageView.contentMode = UIViewContentModeBottom;
            aPressedButtonImageView.backgroundColor = [UIColor clearColor];
            CGRect aPressedButtonLabelFrame = [self.layoutController frameForPressedButtonLabelWithIndex:(i % 10) forNumericInputAccessory:self];
            UILabel *aPressedButtonLabel = [[UILabel alloc] initWithFrame:aPressedButtonLabelFrame];
            aPressedButtonLabel.backgroundColor = [UIColor clearColor];
            aPressedButtonLabel.text = [NSString stringWithFormat: @"%ld", (long)i % 10];
            aPressedButtonLabel.textAlignment = NSTextAlignmentCenter;
            aPressedButtonView.tag = i + 100;

            aPressedButtonLabel.font = [UIFont fontWithName: @"Helvetica-Bold" size: 44.0f];
            aPressedButtonLabel.shadowColor = [UIColor colorWithRed: 0.95f green: 0.95f blue: 0.95f alpha: 1.0f];
            aPressedButtonLabel.shadowOffset = CGSizeMake(0.0f, 0.75f);

            if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication]statusBarOrientation])) {
                aPressedButtonImageView.frame = CGRectMake(aPressedButtonImageView.frame.origin.x, aPressedButtonImageView.frame.origin.y - 2.0f, aPressedButtonImageView.frame.size.width, aPressedButtonImageView.frame.size.height);
            }

            [aPressedButtonView addSubview:aPressedButtonImageView];

            [aPressedButtonView addSubview:aPressedButtonLabel];

            [self addSubview:aPressedButtonView];

        }
    }

    CALayer *aLightGreyBorder = [CALayer layer];
    aLightGreyBorder.frame = CGRectMake(self.bounds.origin.x, self.bounds.origin.y + 1.0f, self.bounds.size.width, 1.0f);
    UIColor *aColor = [UIColor colorWithRed:178.0f/255.0f green:184.0f/255.0f blue:191.0f/255.0f alpha:1.0f];

    aLightGreyBorder.backgroundColor = [aColor CGColor];
    [self.layer insertSublayer:aLightGreyBorder atIndex:0];

    CALayer *aDarkGreyBorder = [CALayer layer];
    aDarkGreyBorder.frame = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, 1.0f);
    UIColor *aSecondColor;

    aSecondColor = [UIColor colorWithRed:100.0f/255.0f green:100.0f/255.0f blue:100.0f/255.0f alpha:1.0f];

    aDarkGreyBorder.backgroundColor = [aSecondColor CGColor];
    [self.layer insertSublayer:aDarkGreyBorder atIndex:0];

    if (self.layoutController.interfaceIdiom == UIUserInterfaceIdiomPhone) {
        for (UIView *aPressedButtonView in [self subviews]) {
            if ([aPressedButtonView isMemberOfClass:[UIView class]]) {
                [self bringSubviewToFront:aPressedButtonView];
            }
        }
    }

    // Now lets add constaints
    [self performSelector:@selector(addConstraintsForButtons:) withObject:buttonsArray afterDelay:1.0];
}

第3步:为所有按钮添加约束(0到9)。在这里,我只显示前2个按钮。

- (void)addConstraintsForButtons:(NSMutableArray *)iButtons {
    // First Button
    MyAccessoryViewNumericButton *firstButton = (MyAccessoryViewNumericButton *)iButtons[0];

    // Left edge constraint for First button
    NSLayoutConstraint *leading =[NSLayoutConstraint
                                  constraintWithItem:firstButton
                                  attribute:NSLayoutAttributeLeading
                                  relatedBy:NSLayoutRelationEqual
                                  toItem:self
                                  attribute:NSLayoutAttributeTrailing
                                  multiplier:1.0f
                                  constant:4.f];

    [self addConstraint:leading];

    // Middle in the super view
    NSLayoutConstraint *vertical =[NSLayoutConstraint
                                   constraintWithItem:firstButton
                                   attribute:NSLayoutAttributeCenterY
                                   relatedBy:NSLayoutRelationEqual
                                   toItem:self
                                   attribute:NSLayoutAttributeCenterY
                                   multiplier:1.0f
                                   constant:0];

    [self addConstraint:vertical];

    // Width-Height Constraint for First button
    [self addWHContraintForButton:firstButton];


    // Second Button
    MyAccessoryViewNumericButton *secondButton = (MyAccessoryViewNumericButton *)iButtons[1];

    // Left edge constraint for First button
    NSLayoutConstraint *secondLeading =[NSLayoutConstraint
                                        constraintWithItem:secondButton
                                        attribute:NSLayoutAttributeLeading
                                        relatedBy:NSLayoutRelationEqual
                                        toItem:firstButton
                                        attribute:NSLayoutAttributeTrailing
                                        multiplier:1.0f
                                        constant:4.f];

    [secondButton addConstraint:secondLeading];

    // Middle in the super view
    NSLayoutConstraint *secondVertical =[NSLayoutConstraint
                                         constraintWithItem:secondButton
                                         attribute:NSLayoutAttributeCenterY
                                         relatedBy:NSLayoutRelationEqual
                                         toItem:firstButton
                                         attribute:NSLayoutAttributeCenterY
                                         multiplier:1.0f
                                         constant:0];

    [secondButton addConstraint:secondVertical];


    // Width-Height Constraint for Second button
    [self addWHContraintForButton:secondButton];

    // Add constaints to rest of the buttons...
}

- (void)addWHContraintForButton:(MyAccessoryViewNumericButton *)iButton {
    CGFloat buttonWidth = 32.0f;
    CGFloat buttonHeight = 44.0f;

    // Height Constraint
    NSLayoutConstraint *height = [NSLayoutConstraint
                                  constraintWithItem:iButton
                                  attribute:NSLayoutAttributeHeight
                                  relatedBy:NSLayoutRelationEqual
                                  toItem:nil
                                  attribute:0
                                  multiplier:0
                                  constant:buttonHeight];

    // Width Constraint
    NSLayoutConstraint *width = [NSLayoutConstraint
                                 constraintWithItem:iButton
                                 attribute:NSLayoutAttributeHeight
                                 relatedBy:NSLayoutRelationEqual
                                 toItem:nil
                                 attribute:0
                                 multiplier:0
                                 constant:buttonWidth];

    [iButton addConstraint:height];
    [iButton addConstraint:width];
}

但是当我运行此代码时,它会崩溃并显示以下消息:

View not found in container hierarchy: <MyAccessoryViewNumericButton: 0x7fb506036f90; baseClass = UIButton; frame = (0 0; 32 44); opaque = NO; tag = 1; layer = <CALayer: 0x7fb506039c70>>
    That view's superview: <MyAccessoryView: 0x7fb503ddfb50; frame = (0 0; 320 46); autoresize = W; layer = <CALayer: 0x7fb503dc1fe0>>

这是我在调试时看到的(通过在keyboardDidShow:didMoveToSuperview方法中设置约束来尝试):

(lldb) po [secondButton superview]
<MyAccessoryView: 0x7fcd6d04f6c0; frame = (0 0; 320 46); autoresize = W; layer = <CALayer: 0x7fcd6adf5ed0>>

(lldb) po [[secondButton superview] superview]
<UIInputSetHostView: 0x7fcd6d0346c0; frame = (0 522; 320 262); layer = <CALayer: 0x7fcd6adef270>>

(lldb) po [[[secondButton superview] superview] superview]
<UIInputSetContainerView: 0x7fcd6d014000; frame = (0 0; 320 568); layer = <CALayer: 0x7fcd6add78d0>>

(lldb) po [[[[secondButton superview] superview] superview] superview]
<UITextEffectsWindow: 0x7fcd6d033c30; frame = (0 0; 320 568); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x7fcd6d034250>>

(lldb) po [[[[[secondButton superview] superview] superview] superview] superview]
0x0000000000000000

虽然视图有父级。有人可以在这里提出建议。

0 个答案:

没有答案